From python-checkins at python.org Sat Feb 1 01:51:40 2014 From: python-checkins at python.org (brian.quinlan) Date: Sat, 1 Feb 2014 01:51:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320319=3A_concurre?= =?utf-8?q?nt=2Efutures=2Ewait=28=29_can_block_forever_even_if_Futures_hav?= =?utf-8?q?e?= Message-ID: <3fGGvw1c58z7Ll9@mail.python.org> http://hg.python.org/cpython/rev/0bcf23a52d55 changeset: 88869:0bcf23a52d55 user: Brian Quinlan date: Sat Feb 01 11:49:04 2014 +1100 summary: Issue #20319: concurrent.futures.wait() can block forever even if Futures have completed files: Lib/concurrent/futures/_base.py | 6 ++++-- Misc/NEWS | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -225,7 +225,8 @@ finally: for f in fs: - f._waiters.remove(waiter) + with f._condition: + f._waiters.remove(waiter) DoneAndNotDoneFutures = collections.namedtuple( 'DoneAndNotDoneFutures', 'done not_done') @@ -272,7 +273,8 @@ waiter.event.wait(timeout) for f in fs: - f._waiters.remove(waiter) + with f._condition: + f._waiters.remove(waiter) done.update(waiter.finished_futures) return DoneAndNotDoneFutures(done, set(fs) - done) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -69,6 +69,12 @@ - Issue #17481: inspect.getfullargspec() now uses inspect.signature() API. +- Issue #15304: concurrent.futures.wait() can block forever even if + Futures have completed. Patch by Glenn Langford. + +Fix warning message when `os.chdir()` fails inside + `test.support.temp_cwd()`. Patch by Chris Jerdonek. + IDLE ---- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 02:08:26 2014 From: python-checkins at python.org (brian.quinlan) Date: Sat, 1 Feb 2014 02:08:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_extra_line_added_in_0b?= =?utf-8?q?cf23a52d55?= Message-ID: <3fGHHG3qG2zMFN@mail.python.org> http://hg.python.org/cpython/rev/4f59b836fa54 changeset: 88870:4f59b836fa54 user: Brian Quinlan date: Sat Feb 01 12:07:54 2014 +1100 summary: Fix extra line added in 0bcf23a52d55 files: Misc/NEWS | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -72,9 +72,6 @@ - Issue #15304: concurrent.futures.wait() can block forever even if Futures have completed. Patch by Glenn Langford. -Fix warning message when `os.chdir()` fails inside - `test.support.temp_cwd()`. Patch by Chris Jerdonek. - IDLE ---- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 02:22:31 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 02:22:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320452=3A_test=5Fa?= =?utf-8?q?syncio_checks_also_the_granularity?= Message-ID: <3fGHbW6mkgz7Lk9@mail.python.org> http://hg.python.org/cpython/rev/a090804862f8 changeset: 88871:a090804862f8 user: Victor Stinner date: Sat Feb 01 02:17:54 2014 +0100 summary: Issue #20452: test_asyncio checks also the granularity files: Lib/test/test_asyncio/test_events.py | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1179,6 +1179,14 @@ calls.append(self.loop._run_once_counter) self.assertEqual(calls, [1, 3, 5, 6]) + def test_granularity(self): + granularity = self.loop._granularity + self.assertGreater(granularity, 0.0) + # Worst expected granularity: 1 ms on Linux (limited by poll/epoll + # resolution), 15.6 ms on Windows (limited by time.monotonic + # resolution) + self.assertLess(granularity, 0.050) + class SubprocessTestsMixin: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 02:22:33 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 02:22:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320452=3A_Fix_test?= =?utf-8?q?=5Ftime=5Fand=5Fcall=5Fat=28=29_of_test=5Fasyncio_on_Windows?= Message-ID: <3fGHbY1270z7Lk9@mail.python.org> http://hg.python.org/cpython/rev/60a960434e5c changeset: 88872:60a960434e5c user: Victor Stinner date: Sat Feb 01 02:18:52 2014 +0100 summary: Issue #20452: Fix test_time_and_call_at() of test_asyncio on Windows Use the granularity to check the minimum time delta, instead of arbitrary value. files: Lib/test/test_asyncio/test_base_events.py | 15 +++++----- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -116,17 +116,18 @@ self.loop.stop() self.loop._process_events = unittest.mock.Mock() - when = self.loop.time() + 0.1 + delay = 0.1 + + when = self.loop.time() + delay self.loop.call_at(when, cb) t0 = self.loop.time() self.loop.run_forever() dt = self.loop.time() - t0 - self.assertTrue(0.09 <= dt <= 0.9, - # Issue #20452: add more info in case of failure, - # to try to investigate the bug - (dt, - self.loop._granularity, - time.get_clock_info('monotonic'))) + + self.assertGreaterEqual(dt, delay - self.loop._granularity, dt) + # tolerate a difference of +800 ms because some Python buildbots + # are really slow + self.assertLessEqual(dt, 0.9, dt) def test_run_once_in_executor_handle(self): def cb(): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 03:19:20 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 03:19:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_document_th?= =?utf-8?q?e_granularity_of_the_event_loop?= Message-ID: <3fGJs40XyFz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/3fea5a721344 changeset: 88873:3fea5a721344 user: Victor Stinner date: Sat Feb 01 02:36:43 2014 +0100 summary: asyncio doc: document the granularity of the event loop Improve also the "Logging" section files: Doc/library/asyncio-dev.rst | 17 +++++++++++------ Doc/library/asyncio-eventloop.rst | 18 +++++++++++++++++- Doc/library/asyncio-task.rst | 3 +++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -7,6 +7,8 @@ This page lists common traps and explains how to avoid them. +.. _asyncio-handle-blocking: + Handle correctly blocking functions ----------------------------------- @@ -21,17 +23,20 @@ different process, to not block the thread of the event loop. See the :func:`BaseEventLoop.run_in_executor` function. +.. seealso:: + + The :ref:`Delayed calls ` section details how the + event loop handles time. + .. _asyncio-logger: -Logger ------- +Logging +------- -.. data:: asyncio.logger.log +The :mod:`asyncio` module logs information with the :mod:`logging` module in +the logger ``'asyncio'``. - :class:`logging.Logger` instance used by :mod:`asyncio` to log messages. - -The logger name is ``'asyncio'``. .. _asyncio-coroutine-not-scheduled: diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -108,6 +108,8 @@ Like :meth:`call_soon`, but thread safe. +.. _asyncio-delayed-calls: + Delayed calls ------------- @@ -116,6 +118,20 @@ implementation; ideally it is a monotonic clock. This will generally be a different clock than :func:`time.time`. +The granularity of the event loop depends on the resolution of the +:meth:`~BaseEventLoop.time` method and the resolution of the selector. It is +usually between 1 ms and 16 ms. For example, a granularity of 1 ms means that +in the best case, the difference between the expected delay and the real +elapsed time is between -1 ms and +1 ms: a call scheduled in 1 nanosecond may +be called in 1 ms, and a call scheduled in 100 ms may be called in 99 ms. + +The granularity is the best difference in theory. In practice, it depends on +the system load and the the time taken by tasks executed by the event loop. +For example, if a task blocks the event loop for 1 second, all tasks scheduled +in this second will be delayed. The :ref:`Handle correctly blocking functions +` section explains how to avoid such issue. + + .. method:: BaseEventLoop.call_later(delay, callback, *args) Arrange for the *callback* to be called after the given *delay* @@ -290,7 +306,7 @@ On Windows, the default event loop uses :class:`selectors.SelectSelector` which only supports sockets. The - :class:`ProactorEventLoop` should be used instead. + :class:`ProactorEventLoop` should be used to support subprocesses. .. note:: diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -441,6 +441,9 @@ time (in seconds). If *result* is provided, it is produced to the caller when the coroutine completes. + The resolution of the sleep depends on the :ref:`granularity of the event + loop `. + .. function:: shield(arg, \*, loop=None) Wait for a future, shielding it from cancellation. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 03:19:21 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 03:19:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_add_=22Conc?= =?utf-8?q?urrency_and_multithreading=22_section?= Message-ID: <3fGJs53YxFz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/a3b4f4b1aedd changeset: 88874:a3b4f4b1aedd user: Victor Stinner date: Sat Feb 01 03:18:58 2014 +0100 summary: asyncio doc: add "Concurrency and multithreading" section files: Doc/library/asyncio-dev.rst | 30 +++++++++++++++++++++-- Doc/library/asyncio-sync.rst | 2 +- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -7,6 +7,32 @@ This page lists common traps and explains how to avoid them. +.. _asyncio-multithreading: + +Concurrency and multithreading +------------------------------ + +An event loop runs in a thread and executes all callbacks and tasks in the same +thread. If a callback should be scheduled from a different thread, the +:meth:`BaseEventLoop.call_soon_threadsafe` method should be used. + +While a task in 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 and the +event loop executes the next task. + +To handle signals and to execute subprocesses, the event loop must be run in +the main thread. + +The :meth:`BaseEventLoop.run_in_executor` method can be used with a thread pool +executor to execute a callback in different thread to not block the thread of +the event loop. + +.. seealso:: + + See the :ref:`Synchronization primitives ` section to + synchronize tasks. + + .. _asyncio-handle-blocking: Handle correctly blocking functions @@ -21,7 +47,7 @@ An executor can be used to run a task in a different thread or even in a different process, to not block the thread of the event loop. See the -:func:`BaseEventLoop.run_in_executor` function. +:meth:`BaseEventLoop.run_in_executor` method. .. seealso:: @@ -213,5 +239,3 @@ yield from asyncio.sleep(2.0) loop.stop() -.. XXX: Document "poll xxx" log message? - diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst --- a/Doc/library/asyncio-sync.rst +++ b/Doc/library/asyncio-sync.rst @@ -1,5 +1,5 @@ .. currentmodule:: asyncio -.. _sync: +.. _asyncio-sync: Synchronization primitives ========================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 03:39:20 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 03:39:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320162=3A_Fix_an_a?= =?utf-8?q?lignment_issue_in_the_siphash24=28=29_hash_function_which?= Message-ID: <3fGKJ80hmMz7Llc@mail.python.org> http://hg.python.org/cpython/rev/caebb4f231da changeset: 88875:caebb4f231da user: Victor Stinner date: Sat Feb 01 03:38:56 2014 +0100 summary: Issue #20162: Fix an alignment issue in the siphash24() hash function which caused a crash on PowerPC 64-bit (ppc64). files: Misc/NEWS | 3 +++ Python/pyhash.c | 2 +- 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #20162: Fix an alignment issue in the siphash24() hash function which + caused a crash on PowerPC 64-bit (ppc64). + Library ------- diff --git a/Python/pyhash.c b/Python/pyhash.c --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -399,7 +399,7 @@ case 7: pt[6] = m[6]; case 6: pt[5] = m[5]; case 5: pt[4] = m[4]; - case 4: *((PY_UINT32_T*)&pt[0]) = *((PY_UINT32_T*)&m[0]); break; + case 4: Py_MEMCPY(pt, m, sizeof(PY_UINT32_T)); break; case 3: pt[2] = m[2]; case 2: pt[1] = m[1]; case 1: pt[0] = m[0]; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 03:54:12 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 03:54:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320354=3A_Fix_alig?= =?utf-8?q?nment_issue_in_the_tracemalloc_module_on_64-bit?= Message-ID: <3fGKdJ6n07z7Lk8@mail.python.org> http://hg.python.org/cpython/rev/fb2cdec2c70c changeset: 88876:fb2cdec2c70c user: Victor Stinner date: Sat Feb 01 03:43:58 2014 +0100 summary: Issue #20354: Fix alignment issue in the tracemalloc module on 64-bit platforms. Bug seen on 64-bit Linux when using "make profile-opt". Only align the "frame_t" structure on 32-bit when Visual Studio is used. Before the alignment to 32-bit was applied to the whole file any compiler supporting "#pragma pack(4)" which includes GCC. files: Modules/_tracemalloc.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -61,10 +61,11 @@ architectures: 12 bytes instead of 16. This optimization might produce SIGBUS on architectures not supporting unaligned memory accesses (64-bit IPS CPU?): on such architecture, the structure must not be packed. */ -#pragma pack(4) typedef struct #ifdef __GNUC__ __attribute__((packed)) +#elif defined(_MSC_VER) +_declspec(align(4)) #endif { PyObject *filename; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 04:07:20 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 04:07:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320354=3A_Mention_?= =?utf-8?q?the_fix_in_Misc/NEWS?= Message-ID: <3fGKwS2ks1z7LkH@mail.python.org> http://hg.python.org/cpython/rev/44b554454971 changeset: 88877:44b554454971 user: Victor Stinner date: Sat Feb 01 03:58:07 2014 +0100 summary: Issue #20354: Mention the fix in Misc/NEWS files: Misc/NEWS | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,9 @@ Library ------- +- Issue #20354: Fix an alignment issue in the tracemalloc module on 64-bit + platforms. Bug seen on 64-bit Linux when using "make profile-opt". + - Issue #17159: inspect.signature now accepts duck types of functions, which adds support for Cython functions. Initial patch by Stefan Behnel. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 04:07:21 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 04:07:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_tracemalloc=3A_Fix_slicing?= =?utf-8?q?_traces_and_fix_slicing_a_traceback=2E?= Message-ID: <3fGKwT4D3tz7Llf@mail.python.org> http://hg.python.org/cpython/rev/72bd45facbd7 changeset: 88878:72bd45facbd7 user: Victor Stinner date: Sat Feb 01 04:07:02 2014 +0100 summary: tracemalloc: Fix slicing traces and fix slicing a traceback. files: Lib/test/test_tracemalloc.py | 10 ++++++++-- Lib/tracemalloc.py | 12 ++++++++---- Misc/NEWS | 2 ++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -123,7 +123,6 @@ self.assertEqual(len(traceback), 1) self.assertEqual(traceback, obj_traceback) - def find_trace(self, traces, traceback): for trace in traces: if trace[1] == traceback._frames: @@ -147,7 +146,6 @@ tracemalloc.stop() self.assertEqual(tracemalloc._get_traces(), []) - def test_get_traces_intern_traceback(self): # dummy wrappers to get more useful and identical frames in the traceback def allocate_bytes2(size): @@ -503,6 +501,14 @@ self.assertEqual(str(stat), 'a.py:5: size=5002 B (+5000 B), count=2 (+1), average=2501 B') + def test_slices(self): + snapshot, snapshot2 = create_snapshots() + self.assertEqual(snapshot.traces[:2], + (snapshot.traces[0], snapshot.traces[1])) + + traceback = snapshot.traces[0].traceback + self.assertEqual(traceback[:2], + (traceback[0], traceback[1])) class TestFilters(unittest.TestCase): diff --git a/Lib/tracemalloc.py b/Lib/tracemalloc.py --- a/Lib/tracemalloc.py +++ b/Lib/tracemalloc.py @@ -182,8 +182,10 @@ return len(self._frames) def __getitem__(self, index): - trace = self._frames[index] - return Frame(trace) + if isinstance(index, slice): + return tuple(Frame(trace) for trace in self._frames[index]) + else: + return Frame(self._frames[index]) def __contains__(self, frame): return frame._frame in self._frames @@ -259,8 +261,10 @@ return len(self._traces) def __getitem__(self, index): - trace = self._traces[index] - return Trace(trace) + if isinstance(index, slice): + return tuple(Trace(trace) for trace in self._traces[index]) + else: + return Trace(self._traces[index]) def __contains__(self, trace): return trace._trace in self._traces diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,8 @@ Library ------- +- tracemalloc: Fix slicing traces and fix slicing a traceback. + - Issue #20354: Fix an alignment issue in the tracemalloc module on 64-bit platforms. Bug seen on 64-bit Linux when using "make profile-opt". -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 04:11:28 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 04:11:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_test=5Fasyncio=3A_relax_ti?= =?utf-8?q?ming=2C_the_=22AMD64_Windows_Server_2008_=5BSB=5D_3=2Ex=22_buil?= =?utf-8?q?dbot?= Message-ID: <3fGL1D2K1jz7LjS@mail.python.org> http://hg.python.org/cpython/rev/0bee98291117 changeset: 88879:0bee98291117 user: Victor Stinner date: Sat Feb 01 04:11:16 2014 +0100 summary: test_asyncio: relax timing, the "AMD64 Windows Server 2008 [SB] 3.x" buildbot looks to be slow files: Lib/test/test_asyncio/test_windows_events.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -105,7 +105,7 @@ self.loop.run_until_complete(f) elapsed = self.loop.time() - start self.assertFalse(f.result()) - self.assertTrue(0.18 < elapsed < 0.5, elapsed) + self.assertTrue(0.18 < elapsed < 0.9, elapsed) _overlapped.SetEvent(event) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 04:26:58 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 04:26:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_test=5Fhash=3A_Fix_a_Bytes?= =?utf-8?q?Warning_in_get=5Fhash=5Fcommand=28=29?= Message-ID: <3fGLM60G0Yz7LjW@mail.python.org> http://hg.python.org/cpython/rev/a29f05545ab5 changeset: 88880:a29f05545ab5 user: Victor Stinner date: Sat Feb 01 04:26:46 2014 +0100 summary: test_hash: Fix a BytesWarning in get_hash_command() files: Lib/test/test_hash.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -172,7 +172,7 @@ # an object to be tested def get_hash_command(self, repr_): - return 'print(hash(eval(%s.decode("utf-8"))))' % repr_.encode("utf-8") + return 'print(hash(eval(%r.decode("utf-8"))))' % repr_.encode("utf-8") def get_hash(self, repr_, seed=None): env = os.environ.copy() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 04:30:59 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 04:30:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_test=5Fhash_on_=22SPAR?= =?utf-8?q?C_Solaris_10_=28cc=252C_64b=29_=5BSB=5D_3=2Ex=22_buildbot?= Message-ID: <3fGLRl3pCnz7LjW@mail.python.org> http://hg.python.org/cpython/rev/22e88355acd6 changeset: 88881:22e88355acd6 user: Victor Stinner date: Sat Feb 01 04:30:48 2014 +0100 summary: Fix test_hash on "SPARC Solaris 10 (cc%2C 64b) [SB] 3.x" buildbot I picked the value from the error message: ====================================================================== FAIL: test_ucs2_string (test.test_hash.StrHashRandomizationTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/cpython/buildslave/cc-64/3.x.snakebite-sol10-sparc-cc-64/build/Lib/test/test_hash.py", line 292, in test_ucs2_string self.assertEqual(self.get_hash(self.repr_ucs2, seed=42), h) AssertionError: -3927695501187247084 != None files: Lib/test/test_hash.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -233,7 +233,8 @@ [44402817, 8998297579845987431, -1956240331, -782697888614047887], # seed 42, '????' - [-283066365, -4576729883824601543, -271871407, None], + [-283066365, -4576729883824601543, -271871407, + -3927695501187247084], ] } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 07:03:33 2014 From: python-checkins at python.org (larry.hastings) Date: Sat, 1 Feb 2014 07:03:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=23Issue_20456=3A_Several_?= =?utf-8?q?improvements_and_bugfixes_for_Argument_Clinic=2C?= Message-ID: <3fGPqn0mLFz7Ljb@mail.python.org> http://hg.python.org/cpython/rev/19d81cc213d7 changeset: 88882:19d81cc213d7 user: Larry Hastings date: Fri Jan 31 22:03:12 2014 -0800 summary: #Issue 20456: Several improvements and bugfixes for Argument Clinic, including correctly generating code for Clinic blocks inside C preprocessor conditional blocks. files: Doc/howto/clinic.rst | 172 +++-- Misc/NEWS | 14 + Modules/_cursesmodule.c | 4 +- Modules/_dbmmodule.c | 42 +- Modules/_opcode.c | 50 +- Modules/clinic/zlibmodule.c.h | 18 +- Modules/posixmodule.c | 36 +- Python/import.c | 12 +- Tools/clinic/clinic.py | 586 ++++++++++++--------- Tools/clinic/clinic_test.py | 49 +- Tools/clinic/cpp.py | 191 +++++++ 11 files changed, 762 insertions(+), 412 deletions(-) diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -561,8 +561,8 @@ to allow full expressions like ``CONSTANT - 1``.) -Renaming the C functions generated by Argument Clinic ------------------------------------------------------ +Renaming the C functions and variables generated by Argument Clinic +------------------------------------------------------------------- Argument Clinic automatically names the functions it generates for you. Occasionally this may cause a problem, if the generated name collides with @@ -584,6 +584,25 @@ and the impl function would now be named ``pickler_dumper_impl()``. +Similarly, you may have a problem where you want to give a parameter +a specific Python name, but that name may be inconvenient in C. Argument +Clinic allows you to give a parameter different names in Python and in C, +using the same ``"as"`` syntax:: + + /*[clinic input] + pickle.Pickler.dump + + obj: object + file as file_obj: object + protocol: object = NULL + * + fix_imports: bool = True + +Here, the name used in Python (in the signature and the ``keywords`` +array) would be ``file``, but the C variable would be named ``file_obj``. + +You can use this to rename the ``self`` parameter too! + Converting functions using PyArg_UnpackTuple -------------------------------------------- @@ -1308,74 +1327,6 @@ (If your function doesn't support keywords, the parsing function generated will throw an exception if it receives any.) -The #ifdef trick ----------------------------------------------- - -If you're converting a function that isn't available on all platforms, -there's a trick you can use to make life a little easier. The existing -code probably looks like this:: - - #ifdef HAVE_FUNCTIONNAME - static module_functionname(...) - { - ... - } - #endif /* HAVE_FUNCTIONNAME */ - -And then in the ``PyMethodDef`` structure at the bottom you'll have:: - - #ifdef HAVE_FUNCTIONNAME - {'functionname', ... }, - #endif /* HAVE_FUNCTIONNAME */ - -In this scenario, you should change the code to look like the following:: - - #ifdef HAVE_FUNCTIONNAME - /*[clinic input] - module.functionname - ... - [clinic start generated code]*/ - static module_functionname(...) - { - ... - } - #endif /* HAVE_FUNCTIONNAME */ - -Run Argument Clinic on the code in this state, then refresh the file in -your editor. Now you'll have the generated code, including the #define -for the ``PyMethodDef``, like so:: - - #ifdef HAVE_FUNCTIONNAME - /*[clinic input] - ... - [clinic start generated code]*/ - ... - #define MODULE_FUNCTIONNAME \ - {'functionname', ... }, - ... - /*[clinic end generated code: checksum=...]*/ - static module_functionname(...) - { - ... - } - #endif /* HAVE_FUNCTIONNAME */ - -Change the #endif at the bottom as follows:: - - #else - #define MODULE_FUNCTIONNAME - #endif /* HAVE_FUNCTIONNAME */ - -Now you can remove the #ifdefs around the ``PyMethodDef`` structure -at the end, and replace those three lines with ``MODULE_FUNCTIONNAME``. -If the function is available, the macro turns into the ``PyMethodDef`` -static value, including the trailing comma; if the function isn't -available, the macro turns into nothing. Perfect! - -(This is the preferred approach for optional functions; in the future, -Argument Clinic may generate the entire ``PyMethodDef`` structure.) - - Changing and redirecting Clinic's output ---------------------------------------- @@ -1491,8 +1442,9 @@ ``output preset`` sets Clinic's output to one of several built-in preset configurations, as follows: - ``original`` - Clinic's starting configuration. + ``block`` + Clinic's original starting configuration. Writes everything + immediately after the input block. Suppress the ``parser_prototype`` and ``docstring_prototype``, write everything else to ``block``. @@ -1640,6 +1592,82 @@ the file was not modified by hand before it gets overwritten. +The #ifdef trick +---------------------------------------------- + +If you're converting a function that isn't available on all platforms, +there's a trick you can use to make life a little easier. The existing +code probably looks like this:: + + #ifdef HAVE_FUNCTIONNAME + static module_functionname(...) + { + ... + } + #endif /* HAVE_FUNCTIONNAME */ + +And then in the ``PyMethodDef`` structure at the bottom the existing code +will have:: + + #ifdef HAVE_FUNCTIONNAME + {'functionname', ... }, + #endif /* HAVE_FUNCTIONNAME */ + +In this scenario, you should enclose the body of your impl function inside the ``#ifdef``, +like so:: + + #ifdef HAVE_FUNCTIONNAME + /*[clinic input] + module.functionname + ... + [clinic start generated code]*/ + static module_functionname(...) + { + ... + } + #endif /* HAVE_FUNCTIONNAME */ + +Then, remove those three lines from the ``PyMethodDef`` structure, +replacing them with the macro Argument Clinic generated:: + + MODULE_FUNCTIONNAME_METHODDEF + +(You can find the real name for this macro inside the generated code. +Or you can calculate it yourself: it's the name of your function as defined +on the first line of your block, but with periods changed to underscores, +uppercased, and ``"_METHODDEF"`` added to the end.) + +Perhaps you're wondering: what if ``HAVE_FUNCTIONNAME`` isn't defined? +The ``MODULE_FUNCTIONNAME_METHODDEF`` macro won't be defined either! + +Here's where Argument Clinic gets very clever. It actually detects that the +Argument Clinic block might be deactivated by the ``#ifdef``. When that +happens, it generates a little extra code that looks like this:: + + #ifndef MODULE_FUNCTIONNAME_METHODDEF + #define MODULE_FUNCTIONNAME_METHODDEF + #endif /* !defined(MODULE_FUNCTIONNAME_METHODDEF) */ + +That means the macro always works. If the function is defined, this turns +into the correct structure, including the trailing comma. If the function is +undefined, this turns into nothing. + +However, this causes one ticklish problem: where should Argument Clinic put this +extra code when using the "block" output preset? It can't go in the output block, +because that could be decativated by the ``#ifdef``. (That's the whole point!) + +In this situation, Argument Clinic writes the extra code to the "buffer" destination. +This may mean that you get a complaint from Argument Clinic:: + + Warning in file "Modules/posixmodule.c" on line 12357: + Destination buffer 'buffer' not empty at end of file, emptying. + +When this happens, just open your file, find the ``dump buffer`` block that +Argument Clinic added to your file (it'll be at the very bottom), then +move it above the ``PyMethodDef`` structure where that macro is used. + + + Using Argument Clinic in Python files ------------------------------------- diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -95,6 +95,20 @@ Tools/Demos ----------- +- #Issue 20456: Argument Clinic now observes the C preprocessor conditional + compilation statements of the C files it parses. When a Clinic block is + inside a conditional code, it adjusts its output to match, including + automatically generating an empty methoddef macro. + +- #Issue 20456: Cloned functions in Argument Clinic now use the correct + name, not the name of the function they were cloned from, for text + strings inside generated code. + +- #Issue 20456: Fixed Argument Clinic's test suite and "--converters" feature. + +- #Issue 20456: Argument Clinic now allows specifying different names + for a parameter in Python and C, using "as" on the parameter line. + - Issue #20326: Argument Clinic now uses a simple, unique signature to annotate text signatures in docstrings, resulting in fewer false positives. "self" parameters are also explicitly marked, allowing diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -584,7 +584,7 @@ [clinic start generated code]*/ PyDoc_STRVAR(curses_window_addch__doc__, -"addch(self, [x, y,] ch, [attr])\n" +"addch([x, y,] ch, [attr])\n" "Paint character ch at (y, x) with attributes attr.\n" "\n" " x\n" @@ -651,7 +651,7 @@ static PyObject * curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int x, int y, PyObject *ch, int group_right_1, long attr) -/*[clinic end generated code: output=e1cdbd4f4e42fc6b input=fe7e3711d5bbf1f6]*/ +/*[clinic end generated code: output=43acb91a5c98f615 input=fe7e3711d5bbf1f6]*/ { PyCursesWindowObject *cwself = (PyCursesWindowObject *)self; int coordinates_group = group_left_1; diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -52,10 +52,11 @@ /*[python input] class dbmobject_converter(self_converter): type = "dbmobject *" - def converter_init(self): + def pre_render(self): + super().pre_render() self.name = 'dp' [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=8a69ac1827811128]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=6ad536357913879a]*/ static PyObject * newdbmobject(const char *file, int flags, int mode) @@ -270,23 +271,21 @@ self: dbmobject key: str(length=True) - [ - default: object - ] + default: object = None / Return the value for key if present, otherwise default. [clinic start generated code]*/ PyDoc_STRVAR(dbm_dbm_get__doc__, -"get(self, key, [default])\n" +"sig=($self, key, default=None)\n" "Return the value for key if present, otherwise default."); #define DBM_DBM_GET_METHODDEF \ {"get", (PyCFunction)dbm_dbm_get, METH_VARARGS, dbm_dbm_get__doc__}, static PyObject * -dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, int group_right_1, PyObject *default_value); +dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, PyObject *default_value); static PyObject * dbm_dbm_get(dbmobject *dp, PyObject *args) @@ -294,37 +293,24 @@ PyObject *return_value = NULL; const char *key; Py_ssize_clean_t key_length; - int group_right_1 = 0; - PyObject *default_value = NULL; + PyObject *default_value = Py_None; - switch (PyTuple_GET_SIZE(args)) { - case 1: - if (!PyArg_ParseTuple(args, "s#:get", &key, &key_length)) - goto exit; - break; - case 2: - if (!PyArg_ParseTuple(args, "s#O:get", &key, &key_length, &default_value)) - goto exit; - group_right_1 = 1; - break; - default: - PyErr_SetString(PyExc_TypeError, "dbm.dbm.get requires 1 to 2 arguments"); - goto exit; - } - return_value = dbm_dbm_get_impl(dp, key, key_length, group_right_1, default_value); + if (!PyArg_ParseTuple(args, + "s#|O:get", + &key, &key_length, &default_value)) + goto exit; + return_value = dbm_dbm_get_impl(dp, key, key_length, default_value); exit: return return_value; } static PyObject * -dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, int group_right_1, PyObject *default_value) -/*[clinic end generated code: output=31d5180d6b36f1ea input=43a561dc2bd1db3b]*/ +dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) +/*[clinic end generated code: output=2bbaf9a187f9b6bf input=aecf5efd2f2b1a3b]*/ { datum dbm_key, val; - if (!group_right_1) - default_value = Py_None; dbm_key.dptr = (char *)key; dbm_key.dsize = key_length; check_dbmobject_open(dp); diff --git a/Modules/_opcode.c b/Modules/_opcode.c --- a/Modules/_opcode.c +++ b/Modules/_opcode.c @@ -11,49 +11,35 @@ _opcode.stack_effect -> int opcode: int - - [ - oparg: int - ] + oparg: object = None / Compute the stack effect of the opcode. [clinic start generated code]*/ PyDoc_STRVAR(_opcode_stack_effect__doc__, -"stack_effect(module, opcode, [oparg])\n" +"sig=($module, opcode, oparg=None)\n" "Compute the stack effect of the opcode."); #define _OPCODE_STACK_EFFECT_METHODDEF \ {"stack_effect", (PyCFunction)_opcode_stack_effect, METH_VARARGS, _opcode_stack_effect__doc__}, static int -_opcode_stack_effect_impl(PyModuleDef *module, int opcode, int group_right_1, int oparg); +_opcode_stack_effect_impl(PyModuleDef *module, int opcode, PyObject *oparg); static PyObject * _opcode_stack_effect(PyModuleDef *module, PyObject *args) { PyObject *return_value = NULL; int opcode; - int group_right_1 = 0; - int oparg = 0; + PyObject *oparg = Py_None; int _return_value; - switch (PyTuple_GET_SIZE(args)) { - case 1: - if (!PyArg_ParseTuple(args, "i:stack_effect", &opcode)) - goto exit; - break; - case 2: - if (!PyArg_ParseTuple(args, "ii:stack_effect", &opcode, &oparg)) - goto exit; - group_right_1 = 1; - break; - default: - PyErr_SetString(PyExc_TypeError, "_opcode.stack_effect requires 1 to 2 arguments"); - goto exit; - } - _return_value = _opcode_stack_effect_impl(module, opcode, group_right_1, oparg); + if (!PyArg_ParseTuple(args, + "i|O:stack_effect", + &opcode, &oparg)) + goto exit; + _return_value = _opcode_stack_effect_impl(module, opcode, oparg); if ((_return_value == -1) && PyErr_Occurred()) goto exit; return_value = PyLong_FromLong((long)_return_value); @@ -63,23 +49,31 @@ } static int -_opcode_stack_effect_impl(PyModuleDef *module, int opcode, int group_right_1, int oparg) -/*[clinic end generated code: output=4689140ffda2494a input=056816407c3d4284]*/ +_opcode_stack_effect_impl(PyModuleDef *module, int opcode, PyObject *oparg) +/*[clinic end generated code: output=4fe636f5db87c0a9 input=2d0a9ee53c0418f5]*/ { int effect; + int oparg_int = 0; if (HAS_ARG(opcode)) { - if (!group_right_1) { + PyObject *i_object; + if (oparg == Py_None) { PyErr_SetString(PyExc_ValueError, "stack_effect: opcode requires oparg but oparg was not specified"); return -1; } + i_object = PyNumber_Index(oparg); + if (!i_object) + return -1; + oparg_int = (int)PyLong_AsLong(oparg); + if ((oparg_int == -1) && PyErr_Occurred()) + return -1; } - else if (group_right_1) { + else if (oparg != Py_None) { PyErr_SetString(PyExc_ValueError, "stack_effect: opcode does not permit oparg but oparg was specified"); return -1; } - effect = PyCompile_OpcodeStackEffect(opcode, oparg); + effect = PyCompile_OpcodeStackEffect(opcode, oparg_int); if (effect == PY_INVALID_STACK_EFFECT) { PyErr_SetString(PyExc_ValueError, "invalid opcode or oparg"); diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -276,6 +276,8 @@ return return_value; } +#if defined(HAVE_ZLIB_COPY) + PyDoc_STRVAR(zlib_Compress_copy__doc__, "sig=($self)\n" "Return a copy of the compression object."); @@ -292,6 +294,14 @@ return zlib_Compress_copy_impl(self); } +#endif /* defined(HAVE_ZLIB_COPY) */ + +#ifndef ZLIB_COMPRESS_COPY_METHODDEF + #define ZLIB_COMPRESS_COPY_METHODDEF +#endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */ + +#if defined(HAVE_ZLIB_COPY) + PyDoc_STRVAR(zlib_Decompress_copy__doc__, "sig=($self)\n" "Return a copy of the decompression object."); @@ -308,6 +318,12 @@ return zlib_Decompress_copy_impl(self); } +#endif /* defined(HAVE_ZLIB_COPY) */ + +#ifndef ZLIB_DECOMPRESS_COPY_METHODDEF + #define ZLIB_DECOMPRESS_COPY_METHODDEF +#endif /* !defined(ZLIB_DECOMPRESS_COPY_METHODDEF) */ + PyDoc_STRVAR(zlib_Decompress_flush__doc__, "sig=($self, length=DEF_BUF_SIZE)\n" "Return a bytes object containing any remaining decompressed data.\n" @@ -408,4 +424,4 @@ return return_value; } -/*[clinic end generated code: output=ad23316b49faf7e6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=21556008559f839c input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2366,21 +2366,26 @@ converter = 'path_converter' def converter_init(self, *, allow_fd=False, nullable=False): + # right now path_t doesn't support default values. + # to support a default value, you'll need to override initialize(). + if self.default is not unspecified: + fail("Can't specify a default to the path_t converter!") + + if self.c_default is not None: + fail("Can't specify a c_default to the path_t converter!") + + self.nullable = nullable + self.allow_fd = allow_fd + + def pre_render(self): def strify(value): return str(int(bool(value))) - # right now path_t doesn't support default values. - # to support a default value, you'll need to override initialize(). - - assert self.default is unspecified - - self.nullable = nullable - self.allow_fd = allow_fd - + # add self.py_name here when merging with posixmodule conversion self.c_default = 'PATH_T_INITIALIZE("{}", {}, {})'.format( self.function.name, - strify(nullable), - strify(allow_fd), + strify(self.nullable), + strify(self.allow_fd), ) def cleanup(self): @@ -2397,7 +2402,7 @@ [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=d702d58a8469cc7d]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=5c9f456f53244fc3]*/ /*[clinic input] @@ -11122,6 +11127,15 @@ #endif /* MS_WINDOWS */ +/*[clinic input] +dump buffer +[clinic start generated code]*/ + +#ifndef OS_TTYNAME_METHODDEF + #define OS_TTYNAME_METHODDEF +#endif /* !defined(OS_TTYNAME_METHODDEF) */ +/*[clinic end generated code: output=5d071bbc8f49ea12 input=524ce2e021e4eba6]*/ + static PyMethodDef posix_methods[] = { diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -2215,6 +2215,15 @@ #endif /* HAVE_DYNAMIC_LOADING */ +/*[clinic input] +dump buffer +[clinic start generated code]*/ + +#ifndef _IMP_LOAD_DYNAMIC_METHODDEF + #define _IMP_LOAD_DYNAMIC_METHODDEF +#endif /* !defined(_IMP_LOAD_DYNAMIC_METHODDEF) */ +/*[clinic end generated code: output=d07c1d4a343a9579 input=524ce2e021e4eba6]*/ + PyDoc_STRVAR(doc_imp, "(Extremely) low-level import machinery bits as used by importlib and imp."); @@ -2230,9 +2239,7 @@ _IMP_INIT_FROZEN_METHODDEF _IMP_IS_BUILTIN_METHODDEF _IMP_IS_FROZEN_METHODDEF -#ifdef HAVE_DYNAMIC_LOADING _IMP_LOAD_DYNAMIC_METHODDEF -#endif _IMP__FIX_CO_FILENAME_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -2324,3 +2331,4 @@ #ifdef __cplusplus } #endif + diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -10,6 +10,8 @@ import atexit import collections import contextlib +import copy +import cpp import functools import hashlib import inspect @@ -359,10 +361,16 @@ stop_line = "" checksum_line = "" + def __init__(self, filename): + pass + @abc.abstractmethod def render(self, clinic, signatures): pass + def parse_line(self, line): + pass + def validate(self): def assert_only_one(attr, *additional_fields): """ @@ -489,6 +497,30 @@ return tuple(accumulator) +def strip_leading_and_trailing_blank_lines(s): + lines = s.rstrip().split('\n') + while lines: + line = lines[0] + if line.strip(): + break + del lines[0] + return '\n'.join(lines) + + at functools.lru_cache() +def normalize_snippet(s, *, indent=0): + """ + Reformats s: + * removes leading and trailing blank lines + * ensures that it does not end with a newline + * dedents so the first nonwhite character on any line is at column "indent" + """ + s = strip_leading_and_trailing_blank_lines(s) + s = textwrap.dedent(s) + if indent: + s = textwrap.indent(s, ' ' * indent) + return s + + class CLanguage(Language): body_prefix = "#" @@ -498,6 +530,14 @@ stop_line = "[{dsl_name} start generated code]*/" checksum_line = "/*[{dsl_name} end generated code: {arguments}]*/" + def __init__(self, filename): + super().__init__(filename) + self.cpp = cpp.Monitor(filename) + self.cpp.fail = fail + + def parse_line(self, line): + self.cpp.writeline(line) + def render(self, clinic, signatures): function = None for o in signatures: @@ -519,184 +559,6 @@ add('"') return ''.join(text) - _templates = {} - # the templates will be run through str.format(), - # so actual curly-braces need to be doubled up. - templates_source = """ -__________________________________________________ - -docstring_prototype - -PyDoc_VAR({c_basename}__doc__); -__________________________________________________ - -docstring_definition - -PyDoc_STRVAR({c_basename}__doc__, -{docstring}); -__________________________________________________ - -impl_definition - -static {impl_return_type} -{c_basename}_impl({impl_parameters}) -__________________________________________________ - -parser_prototype_noargs - -static PyObject * -{c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored)) -__________________________________________________ - -parser_prototype_meth_o - -# SLIGHT HACK -# METH_O uses {impl_parameters} for the parser! - -static PyObject * -{c_basename}({impl_parameters}) -__________________________________________________ - -parser_prototype_varargs - -static PyObject * -{c_basename}({self_type}{self_name}, PyObject *args) -__________________________________________________ - -parser_prototype_keyword - -static PyObject * -{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs) -__________________________________________________ - -parser_prototype_init - -static int -{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs) -__________________________________________________ - -parser_definition_simple_no_parsing - -{{ - return {c_basename}_impl({impl_arguments}); -}} -__________________________________________________ - -parser_definition_start - -{{ - {return_value_declaration} - {declarations} - {initializers} -{empty line} -__________________________________________________ - -parser_definition_end - - {return_conversion} - -{exit_label} - {cleanup} - return return_value; -}} -__________________________________________________ - -parser_definition_impl_call - - {modifications} - {return_value} = {c_basename}_impl({impl_arguments}); -__________________________________________________ - -parser_definition_unpack_tuple - - if (!PyArg_UnpackTuple(args, "{name}", - {unpack_min}, {unpack_max}, - {parse_arguments})) - goto exit; -__________________________________________________ - -parser_definition_parse_tuple - - if (!PyArg_ParseTuple(args, - "{format_units}:{name}", - {parse_arguments})) - goto exit; -__________________________________________________ - -parser_definition_option_groups - {option_group_parsing} - -__________________________________________________ - -parser_definition_parse_tuple_and_keywords - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "{format_units}:{name}", _keywords, - {parse_arguments})) - goto exit; -__________________________________________________ - -parser_definition_no_positional - - if ({self_type_check}!_PyArg_NoPositional("{name}", args)) - goto exit; - -__________________________________________________ - -parser_definition_no_keywords - - if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs)) - goto exit; - -__________________________________________________ - -methoddef_define - -#define {methoddef_name} \\ - {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}}, -__________________________________________________ -""".rstrip() - - title = '' - buffer = [] - line = None - for line in templates_source.split('\n'): - line = line.rstrip() - if line.startswith('# '): - # comment - continue - if line.startswith("_____"): - if not buffer: - continue - assert title not in _templates, "defined template twice: " + repr(title) - buffer = '\n'.join(buffer).rstrip() - buffer = buffer.replace('{empty line}', '') - _templates[title] = buffer - buffer = [] - title = '' - continue - if not title: - if not line: - continue - title = line - continue - if not (line or buffer): - # throw away leading blank lines - continue - buffer.append(line) - - assert not title, 'ensure templates_source ends with ______ (still adding to ' + repr(title) + ")" - - del templates_source - del title - del buffer - del line - - # for name, value in _templates.items(): - # print(name + ":") - # pprint.pprint(value) - # print() - def output_templates(self, f): parameters = list(f.parameters.values()) assert parameters @@ -731,7 +593,7 @@ converters[0].format_unit == 'O' and not new_or_init) - # we have to set seven things before we're done: + # we have to set these things before we're done: # # docstring_prototype # docstring_definition @@ -740,33 +602,72 @@ # parser_prototype # parser_definition # impl_definition - - templates = self._templates + # cpp_if + # cpp_endif + # methoddef_ifndef return_value_declaration = "PyObject *return_value = NULL;" - methoddef_define = templates['methoddef_define'] + methoddef_define = normalize_snippet(""" + #define {methoddef_name} \\ + {{"{name}", (PyCFunction){c_basename}, {methoddef_flags}, {c_basename}__doc__}}, + """) if new_or_init and not f.docstring: docstring_prototype = docstring_definition = '' else: - docstring_prototype = templates['docstring_prototype'] - docstring_definition = templates['docstring_definition'] - impl_definition = templates['impl_definition'] + docstring_prototype = normalize_snippet(""" + PyDoc_VAR({c_basename}__doc__); + """) + docstring_definition = normalize_snippet(""" + PyDoc_STRVAR({c_basename}__doc__, + {docstring}); + """) + impl_definition = normalize_snippet(""" + static {impl_return_type} + {c_basename}_impl({impl_parameters}) + """) impl_prototype = parser_prototype = parser_definition = None + parser_prototype_keyword = normalize_snippet(""" + static PyObject * + {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs) + """) + + parser_prototype_varargs = normalize_snippet(""" + static PyObject * + {c_basename}({self_type}{self_name}, PyObject *args) + """) + + # parser_body_fields remembers the fields passed in to the + # previous call to parser_body. this is used for an awful hack. parser_body_fields = () def parser_body(prototype, *fields): nonlocal parser_body_fields add, output = text_accumulator() add(prototype) parser_body_fields = fields + fields = list(fields) - fields.insert(0, 'parser_definition_start') - fields.append('parser_definition_impl_call') - fields.append('parser_definition_end') + fields.insert(0, normalize_snippet(""" + {{ + {return_value_declaration} + {declarations} + {initializers} + """) + "\n") + # just imagine--your code is here in the middle + fields.append(normalize_snippet(""" + {modifications} + {return_value} = {c_basename}_impl({impl_arguments}); + {return_conversion} + + {exit_label} + {cleanup} + return return_value; + }} + """)) for field in fields: add('\n') - add(templates[field]) + add(field) return output() def insert_keywords(s): @@ -777,26 +678,39 @@ flags = "METH_NOARGS" - parser_prototype = templates['parser_prototype_noargs'] + parser_prototype = normalize_snippet(""" + static PyObject * + {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored)) + """) parser_definition = parser_prototype if default_return_converter: - parser_definition = parser_prototype + '\n' + templates['parser_definition_simple_no_parsing'] + parser_definition = parser_prototype + '\n' + normalize_snippet(""" + {{ + return {c_basename}_impl({impl_arguments}); + }} + """) else: parser_definition = parser_body(parser_prototype) elif meth_o: flags = "METH_O" - # impl_definition = templates['parser_prototype_meth_o'] + + meth_o_prototype = normalize_snippet(""" + static PyObject * + {c_basename}({impl_parameters}) + """) if default_return_converter: # maps perfectly to METH_O, doesn't need a return converter. # so we skip making a parse function # and call directly into the impl function. impl_prototype = parser_prototype = parser_definition = '' - impl_definition = templates['parser_prototype_meth_o'] + impl_definition = meth_o_prototype else: - parser_prototype = templates['parser_prototype_meth_o'] + # SLIGHT HACK + # use impl_parameters for the parser here! + parser_prototype = meth_o_prototype parser_definition = parser_body(parser_prototype) elif has_option_groups: @@ -805,9 +719,9 @@ # in a big switch statement) flags = "METH_VARARGS" - parser_prototype = templates['parser_prototype_varargs'] - - parser_definition = parser_body(parser_prototype, 'parser_definition_option_groups') + parser_prototype = parser_prototype_varargs + + parser_definition = parser_body(parser_prototype, ' {option_group_parsing}') elif positional and all_boring_objects: # positional-only, but no option groups, @@ -815,26 +729,47 @@ # PyArg_UnpackTuple! flags = "METH_VARARGS" - parser_prototype = templates['parser_prototype_varargs'] - - parser_definition = parser_body(parser_prototype, 'parser_definition_unpack_tuple') + parser_prototype = parser_prototype_varargs + + parser_definition = parser_body(parser_prototype, normalize_snippet(""" + if (!PyArg_UnpackTuple(args, "{name}", + {unpack_min}, {unpack_max}, + {parse_arguments})) + goto exit; + """, indent=4)) elif positional: # positional-only, but no option groups # we only need one call to PyArg_ParseTuple flags = "METH_VARARGS" - parser_prototype = templates['parser_prototype_varargs'] - - parser_definition = parser_body(parser_prototype, 'parser_definition_parse_tuple') + parser_prototype = parser_prototype_varargs + + parser_definition = parser_body(parser_prototype, normalize_snippet(""" + if (!PyArg_ParseTuple(args, + "{format_units}:{name}", + {parse_arguments})) + goto exit; + """, indent=4)) else: # positional-or-keyword arguments flags = "METH_VARARGS|METH_KEYWORDS" - parser_prototype = templates['parser_prototype_keyword'] - - parser_definition = parser_body(parser_prototype, 'parser_definition_parse_tuple_and_keywords') + parser_prototype = parser_prototype_keyword + + body = normalize_snippet(""" + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "{format_units}:{name}", _keywords, + {parse_arguments})) + goto exit; + """, indent=4) + parser_definition = parser_body(parser_prototype, normalize_snippet(""" + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "{format_units}:{name}", _keywords, + {parse_arguments})) + goto exit; + """, indent=4)) parser_definition = insert_keywords(parser_definition) @@ -842,10 +777,13 @@ methoddef_define = '' if f.kind == METHOD_NEW: - parser_prototype = templates['parser_prototype_keyword'] + parser_prototype = parser_prototype_keyword else: return_value_declaration = "int return_value = -1;" - parser_prototype = templates['parser_prototype_init'] + parser_prototype = normalize_snippet(""" + static int + {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs) + """) fields = list(parser_body_fields) parses_positional = 'METH_NOARGS' not in flags @@ -854,9 +792,15 @@ assert parses_positional if not parses_keywords: - fields.insert(0, 'parser_definition_no_keywords') + fields.insert(0, normalize_snippet(""" + if ({self_type_check}!_PyArg_NoKeywords("{name}", kwargs)) + goto exit; + """, indent=4)) if not parses_positional: - fields.insert(0, 'parser_definition_no_positional') + fields.insert(0, normalize_snippet(""" + if ({self_type_check}!_PyArg_NoPositional("{name}", args)) + goto exit; + """, indent=4)) parser_definition = parser_body(parser_prototype, *fields) if parses_keywords: @@ -868,6 +812,22 @@ methoddef_define = methoddef_define.replace('{methoddef_flags}', flags) + methoddef_ifndef = '' + conditional = self.cpp.condition() + if not conditional: + cpp_if = cpp_endif = '' + else: + cpp_if = "#if " + conditional + cpp_endif = "#endif /* " + conditional + " */" + + if methoddef_define: + methoddef_ifndef = normalize_snippet(""" + #ifndef {methoddef_name} + #define {methoddef_name} + #endif /* !defined({methoddef_name}) */ + """) + + # add ';' to the end of parser_prototype and impl_prototype # (they mustn't be None, but they could be an empty string.) assert parser_prototype is not None @@ -890,6 +850,9 @@ "parser_prototype" : parser_prototype, "parser_definition" : parser_definition, "impl_definition" : impl_definition, + "cpp_if" : cpp_if, + "cpp_endif" : cpp_endif, + "methoddef_ifndef" : methoddef_ifndef, } # make sure we didn't forget to assign something, @@ -1007,9 +970,8 @@ add, output = text_accumulator() data = CRenderData() - parameters = list(f.parameters.values()) - assert parameters, "We should always have a 'self' at this point!" - + assert f.parameters, "We should always have a 'self' at this point!" + parameters = f.render_parameters converters = [p.converter for p in parameters] templates = self.output_templates(f) @@ -1289,7 +1251,9 @@ def _line(self): self.line_number += 1 - return self.input.pop() + line = self.input.pop() + self.language.parse_line(line) + return line def parse_verbatim_block(self): add, output = text_accumulator() @@ -1515,13 +1479,25 @@ # The callable should not call builtins.print. return_converters = {} +clinic = None class Clinic: presets_text = """ +preset block +everything block +docstring_prototype suppress +parser_prototype suppress +cpp_if suppress +cpp_endif suppress +methoddef_ifndef buffer + preset original everything block docstring_prototype suppress parser_prototype suppress +cpp_if suppress +cpp_endif suppress +methoddef_ifndef buffer preset file everything file @@ -1581,12 +1557,15 @@ d = self.destinations.get self.field_destinations = collections.OrderedDict(( + ('cpp_if', d('suppress')), ('docstring_prototype', d('suppress')), ('docstring_definition', d('block')), ('methoddef_define', d('block')), ('impl_prototype', d('block')), ('parser_prototype', d('suppress')), ('parser_definition', d('block')), + ('cpp_endif', d('suppress')), + ('methoddef_ifndef', d('buffer')), ('impl_definition', d('block')), )) @@ -1752,7 +1731,7 @@ fail("Can't extract file type for file " + repr(filename)) try: - language = extensions[extension]() + language = extensions[extension](filename) except KeyError: fail("Can't identify file type for file " + repr(filename)) @@ -1934,6 +1913,19 @@ self.self_converter = None self.suppress_signature = suppress_signature + self.rendered_parameters = None + + __render_parameters__ = None + @property + def render_parameters(self): + if not self.__render_parameters__: + self.__render_parameters__ = l = [] + for p in self.parameters.values(): + p = p.copy() + p.converter.pre_render() + l.append(p) + return self.__render_parameters__ + @property def methoddef_flags(self): if self.kind in (METHOD_INIT, METHOD_NEW): @@ -1952,6 +1944,25 @@ def __repr__(self): return '' + def copy(self, **overrides): + kwargs = { + 'name': self.name, 'module': self.module, 'parameters': self.parameters, + 'cls': self.cls, 'c_basename': self.c_basename, + 'full_name': self.full_name, + 'return_converter': self.return_converter, 'return_annotation': self.return_annotation, + 'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist, + 'suppress_signature': self.suppress_signature, + } + kwargs.update(overrides) + f = Function(**kwargs) + + parameters = collections.OrderedDict() + for name, value in f.parameters.items(): + value = value.copy(function=f) + parameters[name] = value + f.parameters = parameters + return f + class Parameter: """ @@ -1976,6 +1987,34 @@ def is_keyword_only(self): return self.kind == inspect.Parameter.KEYWORD_ONLY + def copy(self, **overrides): + kwargs = { + 'name': self.name, 'kind': self.kind, 'default':self.default, + 'function': self.function, 'converter': self.converter, 'annotation': self.annotation, + 'docstring': self.docstring, 'group': self.group, + } + kwargs.update(overrides) + if 'converter' not in overrides: + converter = copy.copy(self.converter) + converter.function = kwargs['function'] + kwargs['converter'] = converter + return Parameter(**kwargs) + + + +class LandMine: + # try to access any + def __init__(self, message): + self.__message__ = message + + def __repr__(self): + return '" + + def __getattribute__(self, name): + if name in ('__repr__', '__message__'): + return super().__getattribute__(name) + # raise RuntimeError(repr(name)) + fail("Stepped on a land mine, trying to access attribute " + repr(name) + ":\n" + self.__message__) def add_c_converter(f, name=None): @@ -1994,6 +2033,8 @@ if ((cls.format_unit != 'O&') and (cls.format_unit not in legacy_converters)): legacy_converters[cls.format_unit] = cls + if cls.format_unit: + legacy_converters[cls.format_unit] = cls return cls def add_legacy_c_converter(format_unit, **kwargs): @@ -2005,7 +2046,8 @@ added_f = f else: added_f = functools.partial(f, **kwargs) - legacy_converters[format_unit] = added_f + if format_unit: + legacy_converters[format_unit] = added_f return f return closure @@ -2021,6 +2063,12 @@ parameters must be keyword-only. """ + # The C name to use for this variable. + name = None + + # The Python name to use for this variable. + py_name = None + # The C type to use for this variable. # 'type' should be a Python string specifying the type, e.g. "int". # If this is a pointer type, the type string should end with ' *'. @@ -2109,9 +2157,9 @@ signature_name = None # keep in sync with self_converter.__init__! - def __init__(self, name, function, default=unspecified, *, c_default=None, py_default=None, annotation=unspecified, **kwargs): - self.function = function + def __init__(self, name, py_name, function, default=unspecified, *, c_default=None, py_default=None, annotation=unspecified, **kwargs): self.name = name + self.py_name = py_name if default is not unspecified: if self.default_type and not isinstance(default, (self.default_type, Unknown)): @@ -2130,7 +2178,14 @@ if annotation != unspecified: fail("The 'annotation' parameter is not currently permitted.") + + # this is deliberate, to prevent you from caching information + # about the function in the init. + # (that breaks if we get cloned.) + # so after this change we will noisily fail. + self.function = LandMine("Don't access members of self.function inside converter_init!") self.converter_init(**kwargs) + self.function = function def converter_init(self): pass @@ -2174,7 +2229,7 @@ data.modifications.append('/* modifications for ' + name + ' */\n' + modifications.rstrip()) # keywords - data.keywords.append(original_name) + data.keywords.append(parameter.name) # format_units if self.is_optional() and '|' not in data.format_units: @@ -2291,6 +2346,14 @@ """ return "" + def pre_render(self): + """ + A second initialization function, like converter_init, + called just before rendering. + You are permitted to examine self.function here. + """ + pass + class bool_converter(CConverter): type = 'int' @@ -2609,12 +2672,14 @@ type = None format_unit = '' - def converter_init(self, *, type=None): + self.specified_type = type + + def pre_render(self): f = self.function default_type, default_name = correct_name_for_self(f) self.signature_name = default_name - self.type = type or self.type or default_type + self.type = self.specified_type or self.type or default_type kind = self.function.kind new_or_init = kind in (METHOD_NEW, METHOD_INIT) @@ -3053,7 +3118,7 @@ return if field not in fd: - fail("Invalid field " + repr(field) + ", must be one of:\n " + ", ".join(valid_fields)) + fail("Invalid field " + repr(field) + ", must be one of:\n preset push pop print everything " + " ".join(fd)) fd[field] = d def directive_dump(self, name): @@ -3132,6 +3197,18 @@ # self.block = self.ClinicOutputBlock(self) if self.ignore_line(line): return + + # is it a directive? + fields = shlex.split(line) + directive_name = fields[0] + directive = self.directives.get(directive_name, None) + if directive: + try: + directive(*fields[1:]) + except TypeError as e: + fail(str(e)) + return + self.next(self.state_modulename_name, line) def state_modulename_name(self, line): @@ -3156,17 +3233,6 @@ self.indent.infer(line) - # is it a directive? - fields = shlex.split(line) - directive_name = fields[0] - directive = self.directives.get(directive_name, None) - if directive: - try: - directive(*fields[1:]) - except TypeError as e: - fail(str(e)) - return - # are we cloning? before, equals, existing = line.rpartition('=') if equals: @@ -3188,7 +3254,7 @@ else: existing_function = None if not existing_function: - print("class", cls, "module", module, "exsiting", existing) + print("class", cls, "module", module, "existing", existing) print("cls. functions", cls.functions) fail("Couldn't find existing function " + repr(existing) + "!") @@ -3198,10 +3264,7 @@ if not (existing_function.kind == self.kind and existing_function.coexist == self.coexist): fail("'kind' of function and cloned function don't match! (@classmethod/@staticmethod/@coexist)") - self.function = Function(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename, - return_converter=existing_function.return_converter, kind=existing_function.kind, coexist=existing_function.coexist) - - self.function.parameters = existing_function.parameters.copy() + self.function = existing_function.copy(name=function_name, full_name=full_name, module=module, cls=cls, c_basename=c_basename, docstring='') self.block.signatures.append(self.function) (cls or module).functions.append(self.function) @@ -3272,7 +3335,7 @@ kwargs = {} if cls and type == "PyObject *": kwargs['type'] = cls.typedef - sc = self.function.self_converter = self_converter(name, self.function, **kwargs) + sc = self.function.self_converter = self_converter(name, name, self.function, **kwargs) p_self = Parameter(sc.name, inspect.Parameter.POSITIONAL_ONLY, function=self.function, converter=sc) self.function.parameters[sc.name] = p_self @@ -3411,6 +3474,22 @@ else: fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".a)") + # handle "as" for parameters too + c_name = None + name, have_as_token, trailing = line.partition(' as ') + if have_as_token: + name = name.strip() + if ' ' not in name: + fields = trailing.strip().split(' ') + if not fields: + fail("Invalid 'as' clause!") + c_name = fields[0] + if c_name.endswith(':'): + name += ':' + c_name = c_name[:-1] + fields[0] = name + line = ' '.join(fields) + base, equals, default = line.rpartition('=') if not equals: base = default @@ -3559,7 +3638,9 @@ legacy_str = "legacy " if legacy else "" if name not in dict: fail('{} is not a valid {}converter'.format(name, legacy_str)) - converter = dict[name](parameter_name, self.function, value, **kwargs) + # if you use a c_name for the parameter, we just give that name to the converter + # but the parameter object gets the python name + converter = dict[name](c_name or parameter_name, parameter_name, self.function, value, **kwargs) kind = inspect.Parameter.KEYWORD_ONLY if self.keyword_only else inspect.Parameter.POSITIONAL_OR_KEYWORD @@ -3703,7 +3784,7 @@ return f.docstring add, output = text_accumulator() - parameters = list(f.parameters.values()) + parameters = f.render_parameters ## ## docstring first line @@ -3772,15 +3853,20 @@ name = p.converter.signature_name or p.name a = [] - if isinstance(p.converter, self_converter) and not f.suppress_signature: - # annotate first parameter as being a "self". - # - # if inspect.Signature gets this function, and it's already bound, - # the self parameter will be stripped off. - # - # if it's not bound, it should be marked as positional-only. - a.append('$') - a.append(name) + if isinstance(p.converter, self_converter): + if f.suppress_signature: + continue + else: + # annotate first parameter as being a "self". + # + # if inspect.Signature gets this function, and it's already bound, + # the self parameter will be stripped off. + # + # if it's not bound, it should be marked as positional-only. + a.append('$') + a.append(name) + else: + a.append(name) if p.converter.is_optional(): a.append('=') value = p.converter.py_default diff --git a/Tools/clinic/clinic_test.py b/Tools/clinic/clinic_test.py --- a/Tools/clinic/clinic_test.py +++ b/Tools/clinic/clinic_test.py @@ -13,6 +13,7 @@ import unittest from unittest import TestCase + class FakeConverter: def __init__(self, name, args): self.name = name @@ -41,10 +42,11 @@ def __init__(self): self.converters = FakeConvertersDict() self.legacy_converters = FakeConvertersDict() - self.language = clinic.CLanguage() + self.language = clinic.CLanguage(None) self.filename = None self.block_parser = clinic.BlockParser('', self.language) self.modules = collections.OrderedDict() + self.classes = collections.OrderedDict() clinic.clinic = self self.name = "FakeClinic" self.line_prefix = self.line_suffix = '' @@ -92,7 +94,7 @@ # so it woudl spit out an end line for you. # and since you really already had one, # the last line of the block got corrupted. - c = clinic.Clinic(clinic.CLanguage()) + c = clinic.Clinic(clinic.CLanguage(None)) raw = "/*[clinic]\nfoo\n[clinic]*/" cooked = c.parse(raw).splitlines() end_line = cooked[2].rstrip() @@ -220,7 +222,7 @@ class ClinicBlockParserTest(TestCase): def _test(self, input, output): - language = clinic.CLanguage() + language = clinic.CLanguage(None) blocks = list(clinic.BlockParser(input, language)) writer = clinic.BlockPrinter(language) @@ -250,7 +252,7 @@ """) def _test_clinic(self, input, output): - language = clinic.CLanguage() + language = clinic.CLanguage(None) c = clinic.Clinic(language) c.parsers['inert'] = InertParser(c) c.parsers['copy'] = CopyParser(c) @@ -265,7 +267,7 @@ def [copy start generated code]*/ abc -/*[copy end generated code: checksum=03cfd743661f07975fa2f1220c5194cbaff48451]*/ +/*[copy end generated code: output=03cfd743661f0797 input=7b18d017f89f61cf]*/ xyz """, """ verbatim text here @@ -274,7 +276,7 @@ def [copy start generated code]*/ def -/*[copy end generated code: checksum=7b18d017f89f61cf17d47f92749ea6930a3f1deb]*/ +/*[copy end generated code: output=7b18d017f89f61cf input=7b18d017f89f61cf]*/ xyz """) @@ -297,7 +299,7 @@ def test_param(self): function = self.parse_function("module os\nos.access\n path: int") self.assertEqual("access", function.name) - self.assertEqual(1, len(function.parameters)) + self.assertEqual(2, len(function.parameters)) p = function.parameters['path'] self.assertEqual('path', p.name) self.assertIsInstance(p.converter, clinic.int_converter) @@ -326,10 +328,21 @@ module os os.access follow_symlinks: bool = True + something_else: str = ''""") + p = function.parameters['follow_symlinks'] + self.assertEqual(3, len(function.parameters)) + self.assertIsInstance(function.parameters['something_else'].converter, clinic.str_converter) + + def test_param_default_parameters_out_of_order(self): + s = self.parse_function_should_fail(""" +module os +os.access + follow_symlinks: bool = True something_else: str""") - p = function.parameters['follow_symlinks'] - self.assertEqual(2, len(function.parameters)) - self.assertIsInstance(function.parameters['something_else'].converter, clinic.str_converter) + self.assertEqual(s, """Error on line 0: +Can't have a parameter without a default ('something_else') +after a parameter with a default! +""") def disabled_test_converter_arguments(self): function = self.parse_function("module os\nos.access\n path: path_t(allow_fd=1)") @@ -346,7 +359,7 @@ Perform a stat system call on the given path.""") self.assertEqual(""" -stat(path) +sig=($module, path) Perform a stat system call on the given path. path @@ -366,7 +379,7 @@ Okay, we're done here. """) self.assertEqual(""" -bar(x, y) +sig=($module, x, y) This is the documentation for foo. x @@ -382,7 +395,7 @@ path: str This/used to break Clinic! """) - self.assertEqual("os.stat(path)\n\nThis/used to break Clinic!", function.docstring) + self.assertEqual("sig=($module, path)\n\nThis/used to break Clinic!", function.docstring) def test_c_name(self): function = self.parse_function("module os\nos.stat as os_stat_fn") @@ -538,7 +551,7 @@ """) self.assertEqual(s, ('Error on line 0:\n' - 'Function two_top_groups_on_left has an unsupported group configuration. (Unexpected state 2)\n')) + 'Function two_top_groups_on_left has an unsupported group configuration. (Unexpected state 2.b)\n')) def test_disallowed_grouping__two_top_groups_on_right(self): self.parse_function_should_fail(""" @@ -611,8 +624,8 @@ Docstring """) - self.assertEqual("bar()\nDocstring", function.docstring) - self.assertEqual(0, len(function.parameters)) + self.assertEqual("sig=($module)\nDocstring", function.docstring) + self.assertEqual(1, len(function.parameters)) # self! def test_illegal_module_line(self): self.parse_function_should_fail(""" @@ -706,7 +719,7 @@ Not at column 0! """) self.assertEqual(""" -bar(x, *, y) +sig=($module, x, *, y) Not at column 0! x @@ -720,7 +733,7 @@ path: str This/used to break Clinic! """) - self.assertEqual("stat(path)\nThis/used to break Clinic!", function.docstring) + self.assertEqual("sig=($module, path)\nThis/used to break Clinic!", function.docstring) def test_directive(self): c = FakeClinic() diff --git a/Tools/clinic/cpp.py b/Tools/clinic/cpp.py new file mode 100644 --- /dev/null +++ b/Tools/clinic/cpp.py @@ -0,0 +1,191 @@ +import re +import sys + +def negate(condition): + """ + Returns a CPP conditional that is the opposite of the conditional passed in. + """ + if condition.startswith('!'): + return condition[1:] + return "!" + condition + +class Monitor: + """ + A simple C preprocessor that scans C source and computes, line by line, + what the current C preprocessor #if state is. + + Doesn't handle everything--for example, if you have /* inside a C string, + without a matching */ (also inside a C string), or with a */ inside a C + string but on another line and with preprocessor macros in between... + the parser will get lost. + + Anyway this implementation seems to work well enough for the CPython sources. + """ + + is_a_simple_defined = re.compile(r'^defined\s*\(\s*[A-Za-z0-9_]+\s*\)$').match + + def __init__(self, filename=None, *, verbose=False): + self.stack = [] + self.in_comment = False + self.continuation = None + self.line_number = 0 + self.filename = filename + self.verbose = verbose + + def __repr__(self): + return ''.join(( + '")) + + def status(self): + return str(self.line_number).rjust(4) + ": " + self.condition() + + def condition(self): + """ + Returns the current preprocessor state, as a single #if condition. + """ + return " && ".join(condition for token, condition in self.stack) + + def fail(self, *a): + if self.filename: + filename = " " + self.filename + else: + filename = '' + print("Error at" + filename, "line", self.line_number, ":") + print(" ", ' '.join(str(x) for x in a)) + sys.exit(-1) + + def close(self): + if self.stack: + self.fail("Ended file while still in a preprocessor conditional block!") + + def write(self, s): + for line in s.split("\n"): + self.writeline(line) + + def writeline(self, line): + self.line_number += 1 + line = line.strip() + + def pop_stack(): + if not self.stack: + self.fail("#" + token + " without matching #if / #ifdef / #ifndef!") + return self.stack.pop() + + if self.continuation: + line = self.continuation + line + self.continuation = None + + if not line: + return + + if line.endswith('\\'): + self.continuation = line[:-1].rstrip() + " " + return + + # we have to ignore preprocessor commands inside comments + # + # we also have to handle this: + # /* start + # ... + # */ /* <-- tricky! + # ... + # */ + # and this: + # /* start + # ... + # */ /* also tricky! */ + if self.in_comment: + if '*/' in line: + # snip out the comment and continue + # + # GCC allows + # /* comment + # */ #include + # maybe other compilers too? + _, _, line = line.partition('*/') + self.in_comment = False + + while True: + if '/*' in line: + if self.in_comment: + self.fail("Nested block comment!") + + before, _, remainder = line.partition('/*') + comment, comment_ends, after = remainder.partition('*/') + if comment_ends: + # snip out the comment + line = before.rstrip() + ' ' + after.lstrip() + continue + # comment continues to eol + self.in_comment = True + line = before.rstrip() + break + + # we actually have some // comments + # (but block comments take precedence) + before, line_comment, comment = line.partition('//') + if line_comment: + line = before.rstrip() + + if not line.startswith('#'): + return + + line = line[1:].lstrip() + assert line + + fields = line.split() + token = fields[0].lower() + condition = ' '.join(fields[1:]).strip() + + if_tokens = {'if', 'ifdef', 'ifndef'} + all_tokens = if_tokens | {'elif', 'else', 'endif'} + + if token not in all_tokens: + return + + # cheat a little here, to reuse the implementation of if + if token == 'elif': + pop_stack() + token = 'if' + + if token in if_tokens: + if not condition: + self.fail("Invalid format for #" + token + " line: no argument!") + if token == 'if': + if not self.is_a_simple_defined(condition): + condition = "(" + condition + ")" + else: + fields = condition.split() + if len(fields) != 1: + self.fail("Invalid format for #" + token + " line: should be exactly one argument!") + symbol = fields[0] + condition = 'defined(' + symbol + ')' + if token == 'ifndef': + condition = '!' + condition + + self.stack.append(("if", condition)) + if self.verbose: + print(self.status()) + return + + previous_token, previous_condition = pop_stack() + + if token == 'else': + self.stack.append(('else', negate(previous_condition))) + elif token == 'endif': + pass + if self.verbose: + print(self.status()) + +if __name__ == '__main__': + for filename in sys.argv[1:]: + with open(filename, "rt") as f: + cpp = Monitor(filename, verbose=True) + print() + print(filename) + for line_number, line in enumerate(f.read().split('\n'), 1): + cpp.writeline(line) -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sat Feb 1 09:44:41 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 01 Feb 2014 09:44:41 +0100 Subject: [Python-checkins] Daily reference leaks (a3b4f4b1aedd): sum=0 Message-ID: results for a3b4f4b1aedd on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogtKgKC2', '-x'] From python-checkins at python.org Sat Feb 1 17:32:53 2014 From: python-checkins at python.org (mark.dickinson) Date: Sat, 1 Feb 2014 17:32:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE5Njgz?= =?utf-8?q?=3A_Add_=5F=5Fclosure=5F=5F_and_other_missing_attributes_to_fun?= =?utf-8?q?ction_docs=2E?= Message-ID: <3fGgnx11BNz7Lk8@mail.python.org> http://hg.python.org/cpython/rev/fed468670866 changeset: 88883:fed468670866 branch: 2.7 parent: 88859:ea1f2f1f84a7 user: Mark Dickinson date: Sat Feb 01 16:32:40 2014 +0000 summary: Issue #19683: Add __closure__ and other missing attributes to function docs. files: Doc/reference/datamodel.rst | 54 +++++++++++++----------- 1 files changed, 30 insertions(+), 24 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -486,44 +486,39 @@ +-----------------------+-------------------------------+-----------+ | Attribute | Meaning | | +=======================+===============================+===========+ - | :attr:`func_doc` | The function's documentation | Writable | - | | string, or ``None`` if | | - | | unavailable | | + | :attr:`__doc__` | The function's documentation | Writable | + | :attr:`func_doc` | string, or ``None`` if | | + | | unavailable. | | +-----------------------+-------------------------------+-----------+ - | :attr:`__doc__` | Another way of spelling | Writable | - | | :attr:`func_doc` | | - +-----------------------+-------------------------------+-----------+ - | :attr:`func_name` | The function's name | Writable | - +-----------------------+-------------------------------+-----------+ - | :attr:`__name__` | Another way of spelling | Writable | - | | :attr:`func_name` | | + | :attr:`__name__` | The function's name. | Writable | + | :attr:`func_name` | | | +-----------------------+-------------------------------+-----------+ | :attr:`__module__` | The name of the module the | Writable | | | function was defined in, or | | | | ``None`` if unavailable. | | +-----------------------+-------------------------------+-----------+ - | :attr:`func_defaults` | A tuple containing default | Writable | - | | argument values for those | | + | :attr:`__defaults__` | A tuple containing default | Writable | + | :attr:`func_defaults` | argument values for those | | | | arguments that have defaults, | | | | or ``None`` if no arguments | | - | | have a default value | | + | | have a default value. | | +-----------------------+-------------------------------+-----------+ - | :attr:`func_code` | The code object representing | Writable | - | | the compiled function body. | | + | :attr:`__code__` | The code object representing | Writable | + | :attr:`func_code` | the compiled function body. | | +-----------------------+-------------------------------+-----------+ - | :attr:`func_globals` | A reference to the dictionary | Read-only | - | | that holds the function's | | + | :attr:`__globals__` | A reference to the dictionary | Read-only | + | :attr:`func_globals` | that holds the function's | | | | global variables --- the | | | | global namespace of the | | | | module in which the function | | | | was defined. | | +-----------------------+-------------------------------+-----------+ - | :attr:`func_dict` | The namespace supporting | Writable | - | | arbitrary function | | + | :attr:`__dict__` | The namespace supporting | Writable | + | :attr:`func_dict` | arbitrary function | | | | attributes. | | +-----------------------+-------------------------------+-----------+ - | :attr:`func_closure` | ``None`` or a tuple of cells | Read-only | - | | that contain bindings for the | | + | :attr:`__closure__` | ``None`` or a tuple of cells | Read-only | + | :attr:`func_closure` | that contain bindings for the | | | | function's free variables. | | +-----------------------+-------------------------------+-----------+ @@ -532,6 +527,12 @@ .. versionchanged:: 2.4 ``func_name`` is now writable. + .. versionchanged:: 2.6 + The double-underscore attributes ``__closure__``, ``__code__``, + ``__defaults__``, and ``__globals__`` were introduced as aliases for + the corresponding ``func_*`` attributes for forwards compatibility + with Python 3. + Function objects also support getting and setting arbitrary attributes, which can be used, for example, to attach metadata to functions. Regular attribute dot-notation is used to get and set such attributes. *Note that the current @@ -542,16 +543,21 @@ code object; see the description of internal types below. .. index:: - single: func_doc (function attribute) single: __doc__ (function attribute) single: __name__ (function attribute) single: __module__ (function attribute) single: __dict__ (function attribute) + single: __defaults__ (function attribute) + single: __code__ (function attribute) + single: __globals__ (function attribute) + single: __closure__ (function attribute) + single: func_doc (function attribute) + single: func_name (function attribute) + single: func_dict (function attribute) single: func_defaults (function attribute) - single: func_closure (function attribute) single: func_code (function attribute) single: func_globals (function attribute) - single: func_dict (function attribute) + single: func_closure (function attribute) pair: global; namespace User-defined methods -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 18:27:18 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 1 Feb 2014 18:27:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_move_of_reload?= =?utf-8?q?=2C_update_new_windows-only_ssl_functions_entry=2E?= Message-ID: <3fGj0k1zTdz7Llp@mail.python.org> http://hg.python.org/cpython/rev/b3f034f5000f changeset: 88884:b3f034f5000f parent: 88882:19d81cc213d7 user: R David Murray date: Sat Feb 01 12:27:07 2014 -0500 summary: whatsnew: move of reload, update new windows-only ssl functions entry. files: Doc/whatsnew/3.4.rst | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -765,6 +765,10 @@ it will normally be desirable to override the default implementation for performance reasons. (Contributed by Brett Cannon in :issue:`18072`.) +The :func:`~importlib.reload` function has been moved from :mod:`imp` +to :mod:`importlib`. The :func:`mod.reload` name is retained for +backward compatibility, but is deprecated. + inspect ------- @@ -1062,8 +1066,10 @@ list of the loaded ``CA`` certificates. (Contributed by Christian Heimes in and :issue:`18147`.) -Add :func:`ssl.enum_cert_store` to retrieve certificates and CRL from Windows' -cert store. (Contributed by Christian Heimes in :issue:`17134`.) +Two new windows-only functions, :func:`~ssl.enum_certificates` and +:func:`~ssl.enum_crls` provide the ability to retrieve certificates, +certificate information, and CRLs from the Windows cert store. (Contributed +by Christian Heimes in :issue:`17134`.) Support for server-side SNI using the new :meth:`ssl.SSLContext.set_servername_callback` method. -- Repository URL: http://hg.python.org/cpython From brett at python.org Sat Feb 1 19:20:48 2014 From: brett at python.org (Brett Cannon) Date: Sat, 1 Feb 2014 13:20:48 -0500 Subject: [Python-checkins] cpython: whatsnew: move of reload, update new windows-only ssl functions entry. In-Reply-To: <3fGj0k1zTdz7Llp@mail.python.org> References: <3fGj0k1zTdz7Llp@mail.python.org> Message-ID: On Sat, Feb 1, 2014 at 12:27 PM, r.david.murray wrote: > http://hg.python.org/cpython/rev/b3f034f5000f > changeset: 88884:b3f034f5000f > parent: 88882:19d81cc213d7 > user: R David Murray > date: Sat Feb 01 12:27:07 2014 -0500 > summary: > whatsnew: move of reload, update new windows-only ssl functions entry. > > files: > Doc/whatsnew/3.4.rst | 10 ++++++++-- > 1 files changed, 8 insertions(+), 2 deletions(-) > > > diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst > --- a/Doc/whatsnew/3.4.rst > +++ b/Doc/whatsnew/3.4.rst > @@ -765,6 +765,10 @@ > it will normally be desirable to override the default implementation > for performance reasons. (Contributed by Brett Cannon in :issue:`18072`.) > > +The :func:`~importlib.reload` function has been moved from :mod:`imp` > +to :mod:`importlib`. The :func:`mod.reload` name is retained for > +backward compatibility, but is deprecated. > + > That wording seems confusing to me. It makes it seem like importlib.reload is deprecated when in fact it's the imp module itself. -Brett > > inspect > ------- > @@ -1062,8 +1066,10 @@ > list of the loaded ``CA`` certificates. (Contributed by Christian Heimes > in > and :issue:`18147`.) > > -Add :func:`ssl.enum_cert_store` to retrieve certificates and CRL from > Windows' > -cert store. (Contributed by Christian Heimes in :issue:`17134`.) > +Two new windows-only functions, :func:`~ssl.enum_certificates` and > +:func:`~ssl.enum_crls` provide the ability to retrieve certificates, > +certificate information, and CRLs from the Windows cert store. > (Contributed > +by Christian Heimes in :issue:`17134`.) > > Support for server-side SNI using the new > :meth:`ssl.SSLContext.set_servername_callback` method. > > -- > Repository URL: http://hg.python.org/cpython > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > https://mail.python.org/mailman/listinfo/python-checkins > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Sat Feb 1 19:49:48 2014 From: python-checkins at python.org (yury.selivanov) Date: Sat, 1 Feb 2014 19:49:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=2Etests=3A_Fix_tes?= =?utf-8?q?ts_to_work_on_python_built_with_=27--without-doc-strings=27?= Message-ID: <3fGkqw2nxrz7Ljj@mail.python.org> http://hg.python.org/cpython/rev/b1f214165471 changeset: 88885:b1f214165471 user: Yury Selivanov date: Sat Feb 01 13:49:29 2014 -0500 summary: inspect.tests: Fix tests to work on python built with '--without-doc-strings' #20471 files: Lib/test/test_inspect.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -2193,6 +2193,9 @@ ('bar', 2, ..., "keyword_only")), ...)) + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") + def test_signature_on_class_without_init(self): # Test classes without user-defined __init__ or __new__ class C: pass self.assertEqual(str(inspect.signature(C)), '()') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 20:23:12 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 1 Feb 2014 20:23:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzIwMjg4OiBmaXgg?= =?utf-8?q?handling_of_invalid_numeric_charrefs_in_HTMLParser=2E?= Message-ID: <3fGlZS3QsPz7LjV@mail.python.org> http://hg.python.org/cpython/rev/0d50b5851f38 changeset: 88886:0d50b5851f38 branch: 2.7 parent: 88883:fed468670866 user: Ezio Melotti date: Sat Feb 01 21:20:22 2014 +0200 summary: #20288: fix handling of invalid numeric charrefs in HTMLParser. files: Lib/HTMLParser.py | 6 +++--- Lib/test/test_htmlparser.py | 6 ++++++ Misc/NEWS | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Lib/HTMLParser.py b/Lib/HTMLParser.py --- a/Lib/HTMLParser.py +++ b/Lib/HTMLParser.py @@ -195,9 +195,9 @@ i = self.updatepos(i, k) continue else: - if ";" in rawdata[i:]: #bail by consuming &# - self.handle_data(rawdata[0:2]) - i = self.updatepos(i, 2) + if ";" in rawdata[i:]: # bail by consuming '&#' + self.handle_data(rawdata[i:i+2]) + i = self.updatepos(i, i+2) break elif startswith('&', i): match = entityref.match(rawdata, i) diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -394,6 +394,12 @@ ("data", "&#bad;"), ("endtag", "p"), ]) + # add the [] as a workaround to avoid buffering (see #20288) + self._run_check(["
&#bad;
"], [ + ("starttag", "div", []), + ("data", "&#bad;"), + ("endtag", "div"), + ]) def test_unescape_function(self): parser = HTMLParser.HTMLParser() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -38,6 +38,8 @@ Library ------- +- Issue #20288: fix handling of invalid numeric charrefs in HTMLParser. + - Issue #19456: ntpath.join() now joins relative paths correctly when a drive is present. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 20:23:13 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 1 Feb 2014 20:23:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzIwMjg4OiBmaXgg?= =?utf-8?q?handling_of_invalid_numeric_charrefs_in_HTMLParser=2E?= Message-ID: <3fGlZT5HkYz7Ljg@mail.python.org> http://hg.python.org/cpython/rev/32097f193892 changeset: 88887:32097f193892 branch: 3.3 parent: 88862:7a611b7aae38 user: Ezio Melotti date: Sat Feb 01 21:21:01 2014 +0200 summary: #20288: fix handling of invalid numeric charrefs in HTMLParser. files: Lib/html/parser.py | 6 +++--- Lib/test/test_htmlparser.py | 6 ++++++ Misc/NEWS | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Lib/html/parser.py b/Lib/html/parser.py --- a/Lib/html/parser.py +++ b/Lib/html/parser.py @@ -228,9 +228,9 @@ i = self.updatepos(i, k) continue else: - if ";" in rawdata[i:]: #bail by consuming &# - self.handle_data(rawdata[0:2]) - i = self.updatepos(i, 2) + if ";" in rawdata[i:]: # bail by consuming &# + self.handle_data(rawdata[i:i+2]) + i = self.updatepos(i, i+2) break elif startswith('&', i): match = entityref.match(rawdata, i) diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -151,6 +151,12 @@ ("data", "&#bad;"), ("endtag", "p"), ]) + # add the [] as a workaround to avoid buffering (see #20288) + self._run_check(["
&#bad;
"], [ + ("starttag", "div", []), + ("data", "&#bad;"), + ("endtag", "div"), + ]) def test_unclosed_entityref(self): self._run_check("&entityref foo", [ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,8 @@ Library ------- +- Issue #20288: fix handling of invalid numeric charrefs in HTMLParser. + - Issue #20424: Python implementation of io.StringIO now supports lone surrogates. - Issue #19456: ntpath.join() now joins relative paths correctly when a drive -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 20:23:15 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 1 Feb 2014 20:23:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzIwMjg4OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3fGlZW00wkz7Ljk@mail.python.org> http://hg.python.org/cpython/rev/92b3928bfde1 changeset: 88888:92b3928bfde1 parent: 88885:b1f214165471 parent: 88887:32097f193892 user: Ezio Melotti date: Sat Feb 01 21:22:26 2014 +0200 summary: #20288: merge with 3.3. files: Lib/html/parser.py | 6 +++--- Lib/test/test_htmlparser.py | 6 ++++++ Misc/NEWS | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Lib/html/parser.py b/Lib/html/parser.py --- a/Lib/html/parser.py +++ b/Lib/html/parser.py @@ -264,9 +264,9 @@ i = self.updatepos(i, k) continue else: - if ";" in rawdata[i:]: #bail by consuming &# - self.handle_data(rawdata[0:2]) - i = self.updatepos(i, 2) + if ";" in rawdata[i:]: # bail by consuming &# + self.handle_data(rawdata[i:i+2]) + i = self.updatepos(i, i+2) break elif startswith('&', i): match = entityref.match(rawdata, i) diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -167,6 +167,12 @@ ("data", "&#bad;"), ("endtag", "p"), ]) + # add the [] as a workaround to avoid buffering (see #20288) + self._run_check(["
&#bad;
"], [ + ("starttag", "div", []), + ("data", "&#bad;"), + ("endtag", "div"), + ]) def test_unclosed_entityref(self): self._run_check("&entityref foo", [ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,6 +41,8 @@ ValueError instead of assert for forbidden subprocess_{shell,exec} arguments. (More to follow -- a convenience API for subprocesses.) +- Issue #20288: fix handling of invalid numeric charrefs in HTMLParser. + - Issue #20424: Python implementation of io.StringIO now supports lone surrogates. - Issue #20308: inspect.signature now works on classes without user-defined -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 1 22:54:38 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Feb 2014 22:54:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320400=3A_Merge_Tu?= =?utf-8?q?lip_into_Python=3A_add_the_new_asyncio=2Esubprocess_module?= Message-ID: <3fGpxB4bX4z7Ljm@mail.python.org> http://hg.python.org/cpython/rev/d7ac90c0463a changeset: 88889:d7ac90c0463a user: Victor Stinner date: Sat Feb 01 22:49:59 2014 +0100 summary: Issue #20400: Merge Tulip into Python: add the new asyncio.subprocess module * Add a new asyncio.subprocess module * Add new create_subprocess_exec() and create_subprocess_shell() functions * The new asyncio.subprocess.SubprocessStreamProtocol creates stream readers for stdout and stderr and a stream writer for stdin. * The new asyncio.subprocess.Process class offers an API close to the subprocess.Popen class: - pid, returncode, stdin, stdout and stderr attributes - communicate(), wait(), send_signal(), terminate() and kill() methods * Remove STDIN (0), STDOUT (1) and STDERR (2) constants from base_subprocess and unix_events, to not be confused with the symbols with the same name of subprocess and asyncio.subprocess modules * _ProactorBasePipeTransport.get_write_buffer_size() now counts also the size of the pending write * _ProactorBaseWritePipeTransport._loop_writing() may now pause the protocol if the write buffer size is greater than the high water mark (64 KB by default) files: Lib/asyncio/__init__.py | 2 + Lib/asyncio/base_subprocess.py | 23 +- Lib/asyncio/proactor_events.py | 34 +- Lib/asyncio/subprocess.py | 197 ++++++++++ Lib/asyncio/unix_events.py | 7 +- Lib/test/test_asyncio/test_base_events.py | 15 +- Lib/test/test_asyncio/test_events.py | 8 - Lib/test/test_asyncio/test_subprocess.py | 196 +++++++++ Lib/test/test_asyncio/test_windows_events.py | 2 +- 9 files changed, 434 insertions(+), 50 deletions(-) diff --git a/Lib/asyncio/__init__.py b/Lib/asyncio/__init__.py --- a/Lib/asyncio/__init__.py +++ b/Lib/asyncio/__init__.py @@ -24,6 +24,7 @@ from .protocols import * from .queues import * from .streams import * +from .subprocess import * from .tasks import * from .transports import * @@ -39,5 +40,6 @@ protocols.__all__ + queues.__all__ + streams.__all__ + + subprocess.__all__ + tasks.__all__ + transports.__all__) diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -6,11 +6,6 @@ from . import transports -STDIN = 0 -STDOUT = 1 -STDERR = 2 - - class BaseSubprocessTransport(transports.SubprocessTransport): def __init__(self, loop, protocol, args, shell, @@ -22,11 +17,11 @@ self._pipes = {} if stdin == subprocess.PIPE: - self._pipes[STDIN] = None + self._pipes[0] = None if stdout == subprocess.PIPE: - self._pipes[STDOUT] = None + self._pipes[1] = None if stderr == subprocess.PIPE: - self._pipes[STDERR] = None + self._pipes[2] = None self._pending_calls = collections.deque() self._finished = False self._returncode = None @@ -76,19 +71,19 @@ loop = self._loop if proc.stdin is not None: _, pipe = yield from loop.connect_write_pipe( - lambda: WriteSubprocessPipeProto(self, STDIN), + lambda: WriteSubprocessPipeProto(self, 0), proc.stdin) - self._pipes[STDIN] = pipe + self._pipes[0] = pipe if proc.stdout is not None: _, pipe = yield from loop.connect_read_pipe( - lambda: ReadSubprocessPipeProto(self, STDOUT), + lambda: ReadSubprocessPipeProto(self, 1), proc.stdout) - self._pipes[STDOUT] = pipe + self._pipes[1] = pipe if proc.stderr is not None: _, pipe = yield from loop.connect_read_pipe( - lambda: ReadSubprocessPipeProto(self, STDERR), + lambda: ReadSubprocessPipeProto(self, 2), proc.stderr) - self._pipes[STDERR] = pipe + self._pipes[2] = pipe assert self._pending_calls is not None diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -29,6 +29,7 @@ self._buffer = None # None or bytearray. self._read_fut = None self._write_fut = None + self._pending_write = 0 self._conn_lost = 0 self._closing = False # Set when close() called. self._eof_written = False @@ -68,6 +69,7 @@ if self._read_fut: self._read_fut.cancel() self._write_fut = self._read_fut = None + self._pending_write = 0 self._buffer = None self._loop.call_soon(self._call_connection_lost, exc) @@ -128,11 +130,10 @@ self._low_water = low def get_write_buffer_size(self): - # NOTE: This doesn't take into account data already passed to - # send() even if send() hasn't finished yet. - if not self._buffer: - return 0 - return len(self._buffer) + size = self._pending_write + if self._buffer is not None: + size += len(self._buffer) + return size class _ProactorReadPipeTransport(_ProactorBasePipeTransport, @@ -206,7 +207,7 @@ class _ProactorBaseWritePipeTransport(_ProactorBasePipeTransport, - transports.WriteTransport): + transports.WriteTransport): """Transport for write pipes.""" def write(self, data): @@ -252,6 +253,7 @@ try: assert f is self._write_fut self._write_fut = None + self._pending_write = 0 if f: f.result() if data is None: @@ -262,15 +264,21 @@ self._loop.call_soon(self._call_connection_lost, None) if self._eof_written: self._sock.shutdown(socket.SHUT_WR) + # Now that we've reduced the buffer size, tell the + # protocol to resume writing if it was paused. Note that + # we do this last since the callback is called immediately + # and it may add more data to the buffer (even causing the + # protocol to be paused again). + self._maybe_resume_protocol() else: self._write_fut = self._loop._proactor.send(self._sock, data) - self._write_fut.add_done_callback(self._loop_writing) - # Now that we've reduced the buffer size, tell the - # protocol to resume writing if it was paused. Note that - # we do this last since the callback is called immediately - # and it may add more data to the buffer (even causing the - # protocol to be paused again). - self._maybe_resume_protocol() + if not self._write_fut.done(): + assert self._pending_write == 0 + self._pending_write = len(data) + self._write_fut.add_done_callback(self._loop_writing) + self._maybe_pause_protocol() + else: + self._write_fut.add_done_callback(self._loop_writing) except ConnectionResetError as exc: self._force_close(exc) except OSError as exc: diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py new file mode 100644 --- /dev/null +++ b/Lib/asyncio/subprocess.py @@ -0,0 +1,197 @@ +__all__ = ['create_subprocess_exec', 'create_subprocess_shell'] + +import collections +import subprocess + +from . import events +from . import futures +from . import protocols +from . import streams +from . import tasks + + +PIPE = subprocess.PIPE +STDOUT = subprocess.STDOUT +DEVNULL = subprocess.DEVNULL + + +class SubprocessStreamProtocol(streams.FlowControlMixin, + protocols.SubprocessProtocol): + """Like StreamReaderProtocol, but for a subprocess.""" + + def __init__(self, limit, loop): + super().__init__(loop=loop) + self._limit = limit + self.stdin = self.stdout = self.stderr = None + self.waiter = futures.Future(loop=loop) + self._waiters = collections.deque() + self._transport = None + + def connection_made(self, transport): + self._transport = transport + if transport.get_pipe_transport(1): + self.stdout = streams.StreamReader(limit=self._limit, + loop=self._loop) + if transport.get_pipe_transport(2): + self.stderr = streams.StreamReader(limit=self._limit, + loop=self._loop) + stdin = transport.get_pipe_transport(0) + if stdin is not None: + self.stdin = streams.StreamWriter(stdin, + protocol=self, + reader=None, + loop=self._loop) + self.waiter.set_result(None) + + def pipe_data_received(self, fd, data): + if fd == 1: + reader = self.stdout + elif fd == 2: + reader = self.stderr + else: + reader = None + if reader is not None: + reader.feed_data(data) + + def pipe_connection_lost(self, fd, exc): + if fd == 0: + pipe = self.stdin + if pipe is not None: + pipe.close() + self.connection_lost(exc) + return + if fd == 1: + reader = self.stdout + elif fd == 2: + reader = self.stderr + else: + reader = None + if reader != None: + if exc is None: + reader.feed_eof() + else: + reader.set_exception(exc) + + def process_exited(self): + # wake up futures waiting for wait() + returncode = self._transport.get_returncode() + while self._waiters: + waiter = self._waiters.popleft() + waiter.set_result(returncode) + + +class Process: + def __init__(self, transport, protocol, loop): + self._transport = transport + self._protocol = protocol + self._loop = loop + self.stdin = protocol.stdin + self.stdout = protocol.stdout + self.stderr = protocol.stderr + self.pid = transport.get_pid() + + @property + def returncode(self): + return self._transport.get_returncode() + + @tasks.coroutine + def wait(self): + """Wait until the process exit and return the process return code.""" + returncode = self._transport.get_returncode() + if returncode is not None: + return returncode + + waiter = futures.Future(loop=self._loop) + self._protocol._waiters.append(waiter) + yield from waiter + return waiter.result() + + def get_subprocess(self): + return self._transport.get_extra_info('subprocess') + + def _check_alive(self): + if self._transport.get_returncode() is not None: + raise ProcessLookupError() + + def send_signal(self, signal): + self._check_alive() + self._transport.send_signal(signal) + + def terminate(self): + self._check_alive() + self._transport.terminate() + + def kill(self): + self._check_alive() + self._transport.kill() + + @tasks.coroutine + def _feed_stdin(self, input): + self.stdin.write(input) + yield from self.stdin.drain() + self.stdin.close() + + @tasks.coroutine + def _noop(self): + return None + + @tasks.coroutine + def _read_stream(self, fd): + transport = self._transport.get_pipe_transport(fd) + if fd == 2: + stream = self.stderr + else: + assert fd == 1 + stream = self.stdout + output = yield from stream.read() + transport.close() + return output + + @tasks.coroutine + def communicate(self, input=None): + loop = self._transport._loop + if input: + stdin = self._feed_stdin(input) + else: + stdin = self._noop() + if self.stdout is not None: + stdout = self._read_stream(1) + else: + stdout = self._noop() + if self.stderr is not None: + stderr = self._read_stream(2) + else: + stderr = self._noop() + stdin, stdout, stderr = yield from tasks.gather(stdin, stdout, stderr, + loop=loop) + yield from self.wait() + return (stdout, stderr) + + + at tasks.coroutine +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) + yield from protocol.waiter + return Process(transport, protocol, loop) + + at tasks.coroutine +def create_subprocess_exec(*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, + *args, stdin=stdin, stdout=stdout, + stderr=stderr, **kwds) + yield from protocol.waiter + return Process(transport, protocol, loop) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -21,16 +21,11 @@ from .log import logger -__all__ = ['SelectorEventLoop', 'STDIN', 'STDOUT', 'STDERR', +__all__ = ['SelectorEventLoop', 'AbstractChildWatcher', 'SafeChildWatcher', 'FastChildWatcher', 'DefaultEventLoopPolicy', ] -STDIN = 0 -STDOUT = 1 -STDERR = 2 - - if sys.platform == 'win32': # pragma: no cover raise ImportError('Signals are not really supported on Windows') diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -116,18 +116,17 @@ self.loop.stop() self.loop._process_events = unittest.mock.Mock() - delay = 0.1 - - when = self.loop.time() + delay + when = self.loop.time() + 0.1 self.loop.call_at(when, cb) t0 = self.loop.time() self.loop.run_forever() dt = self.loop.time() - t0 - - self.assertGreaterEqual(dt, delay - self.loop._granularity, dt) - # tolerate a difference of +800 ms because some Python buildbots - # are really slow - self.assertLessEqual(dt, 0.9, dt) + self.assertTrue(0.09 <= dt <= 0.9, + # Issue #20452: add more info in case of failure, + # to try to investigate the bug + (dt, + self.loop._granularity, + time.get_clock_info('monotonic'))) def test_run_once_in_executor_handle(self): def cb(): diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1179,14 +1179,6 @@ calls.append(self.loop._run_once_counter) self.assertEqual(calls, [1, 3, 5, 6]) - def test_granularity(self): - granularity = self.loop._granularity - self.assertGreater(granularity, 0.0) - # Worst expected granularity: 1 ms on Linux (limited by poll/epoll - # resolution), 15.6 ms on Windows (limited by time.monotonic - # resolution) - self.assertLess(granularity, 0.050) - class SubprocessTestsMixin: diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -0,0 +1,196 @@ +from asyncio import subprocess +import asyncio +import signal +import sys +import unittest +from test import support +if sys.platform != 'win32': + from asyncio import unix_events + +# Program exiting quickly +PROGRAM_EXIT_FAST = [sys.executable, '-c', 'pass'] + +# Program blocking +PROGRAM_BLOCKED = [sys.executable, '-c', 'import time; time.sleep(3600)'] + +# Program sleeping during 1 second +PROGRAM_SLEEP_1SEC = [sys.executable, '-c', 'import time; time.sleep(1)'] + +# Program copying input to output +PROGRAM_CAT = [ + sys.executable, '-c', + ';'.join(('import sys', + 'data = sys.stdin.buffer.read()', + 'sys.stdout.buffer.write(data)'))] + +class SubprocessMixin: + def test_stdin_stdout(self): + args = PROGRAM_CAT + + @asyncio.coroutine + def run(data): + proc = yield from asyncio.create_subprocess_exec( + *args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + loop=self.loop) + + # feed data + proc.stdin.write(data) + yield from proc.stdin.drain() + proc.stdin.close() + + # get output and exitcode + data = yield from proc.stdout.read() + exitcode = yield from proc.wait() + return (exitcode, data) + + task = run(b'some data') + task = asyncio.wait_for(task, 10.0, loop=self.loop) + exitcode, stdout = self.loop.run_until_complete(task) + self.assertEqual(exitcode, 0) + self.assertEqual(stdout, b'some data') + + def test_communicate(self): + args = PROGRAM_CAT + + @asyncio.coroutine + def run(data): + proc = yield from asyncio.create_subprocess_exec( + *args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + loop=self.loop) + stdout, stderr = yield from proc.communicate(data) + return proc.returncode, stdout + + task = run(b'some data') + task = asyncio.wait_for(task, 10.0, loop=self.loop) + exitcode, stdout = self.loop.run_until_complete(task) + self.assertEqual(exitcode, 0) + self.assertEqual(stdout, b'some data') + + def test_shell(self): + create = asyncio.create_subprocess_shell('exit 7', + loop=self.loop) + proc = self.loop.run_until_complete(create) + exitcode = self.loop.run_until_complete(proc.wait()) + self.assertEqual(exitcode, 7) + + def test_start_new_session(self): + # start the new process in a new session + create = asyncio.create_subprocess_shell('exit 8', + start_new_session=True, + loop=self.loop) + proc = self.loop.run_until_complete(create) + exitcode = self.loop.run_until_complete(proc.wait()) + self.assertEqual(exitcode, 8) + + def test_kill(self): + args = PROGRAM_BLOCKED + create = asyncio.create_subprocess_exec(*args, loop=self.loop) + proc = self.loop.run_until_complete(create) + proc.kill() + returncode = self.loop.run_until_complete(proc.wait()) + if sys.platform == 'win32': + self.assertIsInstance(returncode, int) + # expect 1 but sometimes get 0 + else: + self.assertEqual(-signal.SIGKILL, returncode) + + def test_terminate(self): + args = PROGRAM_BLOCKED + create = asyncio.create_subprocess_exec(*args, loop=self.loop) + proc = self.loop.run_until_complete(create) + proc.terminate() + returncode = self.loop.run_until_complete(proc.wait()) + if sys.platform == 'win32': + self.assertIsInstance(returncode, int) + # expect 1 but sometimes get 0 + else: + self.assertEqual(-signal.SIGTERM, returncode) + + @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") + def test_send_signal(self): + args = PROGRAM_BLOCKED + create = asyncio.create_subprocess_exec(*args, loop=self.loop) + proc = self.loop.run_until_complete(create) + proc.send_signal(signal.SIGHUP) + returncode = self.loop.run_until_complete(proc.wait()) + self.assertEqual(-signal.SIGHUP, returncode) + + def test_get_subprocess(self): + args = PROGRAM_EXIT_FAST + + @asyncio.coroutine + def run(): + proc = yield from asyncio.create_subprocess_exec(*args, + loop=self.loop) + yield from proc.wait() + + popen = proc.get_subprocess() + popen.wait() + return (proc, popen) + + proc, popen = self.loop.run_until_complete(run()) + self.assertEqual(popen.returncode, proc.returncode) + self.assertEqual(popen.pid, proc.pid) + + def test_broken_pipe(self): + large_data = b'x' * support.PIPE_MAX_SIZE + + create = asyncio.create_subprocess_exec( + *PROGRAM_SLEEP_1SEC, + stdin=subprocess.PIPE, + loop=self.loop) + proc = self.loop.run_until_complete(create) + with self.assertRaises(BrokenPipeError): + self.loop.run_until_complete(proc.communicate(large_data)) + self.loop.run_until_complete(proc.wait()) + + +if sys.platform != 'win32': + # Unix + class SubprocessWatcherMixin(SubprocessMixin): + Watcher = None + + def setUp(self): + policy = asyncio.get_event_loop_policy() + self.loop = policy.new_event_loop() + + # ensure that the event loop is passed explicitly in the code + policy.set_event_loop(None) + + watcher = self.Watcher() + watcher.attach_loop(self.loop) + policy.set_child_watcher(watcher) + + def tearDown(self): + policy = asyncio.get_event_loop_policy() + policy.set_child_watcher(None) + self.loop.close() + policy.set_event_loop(None) + + class SubprocessSafeWatcherTests(SubprocessWatcherMixin, unittest.TestCase): + Watcher = unix_events.SafeChildWatcher + + class SubprocessFastWatcherTests(SubprocessWatcherMixin, unittest.TestCase): + Watcher = unix_events.FastChildWatcher +else: + # Windows + class SubprocessProactorTests(SubprocessMixin, unittest.TestCase): + def setUp(self): + policy = asyncio.get_event_loop_policy() + self.loop = asyncio.ProactorEventLoop() + + # ensure that the event loop is passed explicitly in the code + policy.set_event_loop(None) + + def tearDown(self): + policy = asyncio.get_event_loop_policy() + self.loop.close() + policy.set_event_loop(None) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -105,7 +105,7 @@ self.loop.run_until_complete(f) elapsed = self.loop.time() - start self.assertFalse(f.result()) - self.assertTrue(0.18 < elapsed < 0.9, elapsed) + self.assertTrue(0.18 < elapsed < 0.5, elapsed) _overlapped.SetEvent(event) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 05:15:26 2014 From: python-checkins at python.org (terry.reedy) Date: Sun, 2 Feb 2014 05:15:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Update_the_pyt?= =?utf-8?q?hon=2Egif_icon_for_the_Idle_classbrowser_and_pathbowser?= Message-ID: <3fGzNZ63qlz7Ljf@mail.python.org> http://hg.python.org/cpython/rev/ae1c70135763 changeset: 88890:ae1c70135763 branch: 2.7 parent: 88886:0d50b5851f38 user: Terry Jan Reedy date: Sat Feb 01 23:08:24 2014 -0500 summary: Update the python.gif icon for the Idle classbrowser and pathbowser from the old green snake to the new new blue and yellow snakes. files: Lib/idlelib/Icons/python.gif | Bin 1 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/Icons/python.gif b/Lib/idlelib/Icons/python.gif index 58271edec49353382f935ada2de138a1f5b35d9a..b189c2c2d22c120800daefebf9b8bb26f60857a0 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 05:15:28 2014 From: python-checkins at python.org (terry.reedy) Date: Sun, 2 Feb 2014 05:15:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Update_the_pyt?= =?utf-8?q?hon=2Egif_icon_for_the_Idle_classbrowser_and_pathbowser?= Message-ID: <3fGzNc0YDjz7Ljt@mail.python.org> http://hg.python.org/cpython/rev/412a8e2c2af6 changeset: 88891:412a8e2c2af6 branch: 3.3 parent: 88887:32097f193892 user: Terry Jan Reedy date: Sat Feb 01 23:08:33 2014 -0500 summary: Update the python.gif icon for the Idle classbrowser and pathbowser from the old green snake to the new new blue and yellow snakes. files: Lib/idlelib/Icons/python.gif | Bin Misc/NEWS | 3 +++ 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/Icons/python.gif b/Lib/idlelib/Icons/python.gif index 58271edec49353382f935ada2de138a1f5b35d9a..b189c2c2d22c120800daefebf9b8bb26f60857a0 GIT binary patch [stripped] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -286,6 +286,9 @@ IDLE ---- +- Update the python.gif icon for the Idle classbrowser and pathbowser + from the old green snake to the new new blue and yellow snakes. + - Issue #17721: Remove non-functional configuration dialog help button until we make it actually gives some help when clicked. Patch by Guilherme Sim?es. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 05:15:29 2014 From: python-checkins at python.org (terry.reedy) Date: Sun, 2 Feb 2014 05:15:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Update_the_python=2Egif_icon_for_the_Idle_classbrowser_a?= =?utf-8?q?nd_pathbowser?= Message-ID: <3fGzNd2S8Fz7LkD@mail.python.org> http://hg.python.org/cpython/rev/5e0f9b8e6c2b changeset: 88892:5e0f9b8e6c2b parent: 88889:d7ac90c0463a parent: 88891:412a8e2c2af6 user: Terry Jan Reedy date: Sat Feb 01 23:14:59 2014 -0500 summary: Update the python.gif icon for the Idle classbrowser and pathbowser from the old green snake to the new new blue and yellow snakes. files: Lib/idlelib/Icons/python.gif | Bin Misc/NEWS | 3 +++ 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/Icons/python.gif b/Lib/idlelib/Icons/python.gif index 58271edec49353382f935ada2de138a1f5b35d9a..b189c2c2d22c120800daefebf9b8bb26f60857a0 GIT binary patch [stripped] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -85,6 +85,9 @@ IDLE ---- +- Update the python.gif icon for the Idle classbrowser and pathbowser + from the old green snake to the new new blue and yellow snakes. + - Issue #17721: Remove non-functional configuration dialog help button until we make it actually gives some help when clicked. Patch by Guilherme Sim?es. -- Repository URL: http://hg.python.org/cpython From tjreedy at udel.edu Sun Feb 2 05:25:17 2014 From: tjreedy at udel.edu (Terry Reedy) Date: Sat, 01 Feb 2014 23:25:17 -0500 Subject: [Python-checkins] cpython (2.7): Update the python.gif icon for the Idle classbrowser and pathbowser In-Reply-To: <3fGzNZ63qlz7Ljf@mail.python.org> References: <3fGzNZ63qlz7Ljf@mail.python.org> Message-ID: <52EDC8AD.4070707@udel.edu> On 2/1/2014 11:15 PM, terry.reedy wrote: > http://hg.python.org/cpython/rev/ae1c70135763 > changeset: 88890:ae1c70135763 > branch: 2.7 > parent: 88886:0d50b5851f38 > user: Terry Jan Reedy > date: Sat Feb 01 23:08:24 2014 -0500 > summary: > Update the python.gif icon for the Idle classbrowser and pathbowser > from the old green snake to the new new blue and yellow snakes. > > files: > Lib/idlelib/Icons/python.gif | Bin > 1 files changed, 0 insertions(+), 0 deletions(-) > > > diff --git a/Lib/idlelib/Icons/python.gif b/Lib/idlelib/Icons/python.gif > index 58271edec49353382f935ada2de138a1f5b35d9a..b189c2c2d22c120800daefebf9b8bb26f60857a0 > GIT binary patch > [stripped] I deleted the NEWS item added to 3.3/4 IDLE ---- +- Update the python.gif icon for the Idle classbrowser and pathbowser + from the old green snake to the new new blue and yellow snakes. + - Issue #17721: Remove non-functional configuration dialog help button until we make it actually gives some help when clicked. Patch by Guilherme Sim?es. because the pre-commit diff for 2.7 was to delete all ~10000 lines and add back 3 more. This has happened before and is the 2nd thing I hate about NEWS, other than merge conflicts (which happened for the 3.3 to 3.4 merge). Terry From solipsis at pitrou.net Sun Feb 2 09:46:39 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 02 Feb 2014 09:46:39 +0100 Subject: [Python-checkins] Daily reference leaks (d7ac90c0463a): sum=9 Message-ID: results for d7ac90c0463a on branch "default" -------------------------------------------- test__opcode leaked [3, 3, 3] references, sum=9 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogu451k0', '-x'] From python-checkins at python.org Sun Feb 2 15:04:47 2014 From: python-checkins at python.org (victor.stinner) Date: Sun, 2 Feb 2014 15:04:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_add_=22asyn?= =?utf-8?q?cio-=22_prefix_to_references?= Message-ID: <3fHDSb6TF4z7Ljn@mail.python.org> http://hg.python.org/cpython/rev/5141dd05bc44 changeset: 88893:5141dd05bc44 user: Victor Stinner date: Sun Feb 02 15:03:02 2014 +0100 summary: asyncio doc: add "asyncio-" prefix to references files: Doc/library/asyncio-dev.rst | 2 +- Doc/library/asyncio-eventloop.rst | 12 ++++++------ Doc/library/asyncio-protocol.rst | 10 +++++----- Doc/library/asyncio-stream.rst | 2 +- Doc/library/asyncio.rst | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -43,7 +43,7 @@ important impact on reactivity. For networking and subprocesses, the :mod:`asyncio` module provides high-level -APIs like :ref:`protocols `. +APIs like :ref:`protocols `. An executor can be used to run a task in a different thread or even in a different process, to not block the thread of the event loop. See the diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -1,6 +1,6 @@ .. currentmodule:: asyncio -.. _event-loop: +.. _asyncio-event-loop: Event loops =========== @@ -10,10 +10,10 @@ * Registering, executing and cancelling delayed calls (timeouts) -* Creating client and server :ref:`transports ` for various +* Creating client and server :ref:`transports ` for various kinds of communication -* Launching subprocesses and the associated :ref:`transports ` +* Launching subprocesses and the associated :ref:`transports ` for communication with an external program * Delegating costly function calls to a pool of threads @@ -172,7 +172,7 @@ Create a streaming transport connection to a given Internet *host* and *port*. *protocol_factory* must be a callable returning a - :ref:`protocol ` instance. + :ref:`protocol ` instance. This method returns a :ref:`coroutine object ` which will try to establish the connection in the background. When successful, the @@ -180,11 +180,11 @@ The chronological synopsis of the underlying operation is as follows: - #. The connection is established, and a :ref:`transport ` + #. The connection is established, and a :ref:`transport ` is created to represent it. #. *protocol_factory* is called without arguments and must return a - :ref:`protocol ` instance. + :ref:`protocol ` instance. #. The protocol instance is tied to the transport, and its :meth:`connection_made` method is called. diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -4,7 +4,7 @@ Transports and protocols (low-level API) +++++++++++++++++++++++++++++++++++++++++ -.. _transport: +.. _asyncio-transport: Transports ========== @@ -16,7 +16,7 @@ communication channel, calling you back when it succeeds. Once the communication channel is established, a transport is always -paired with a :ref:`protocol ` instance. The protocol can +paired with a :ref:`protocol ` instance. The protocol can then call the transport's methods for various purposes. :mod:`asyncio` currently implements transports for TCP, UDP, SSL, and @@ -228,14 +228,14 @@ stop the subprocess. -.. _protocol: +.. _asyncio-protocol: Protocols ========= :mod:`asyncio` provides base classes that you can subclass to implement your network protocols. Those classes are used in conjunction with -:ref:`transports ` (see below): the protocol parses incoming +:ref:`transports ` (see below): the protocol parses incoming data and asks for the writing of outgoing data, while the transport is responsible for the actual I/O and buffering. @@ -410,7 +410,7 @@ is not guarantee on 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 +To have a reliable execution order, use :ref:`stream objects ` in a coroutine with ``yield from``. For example, the :meth:`StreamWriter.drain` coroutine can be used to wait until the write buffer is flushed. diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -1,6 +1,6 @@ .. currentmodule:: asyncio -.. _streams: +.. _asyncio-streams: ++++++++++++++++++++++++ Streams (high-level API) diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst --- a/Doc/library/asyncio.rst +++ b/Doc/library/asyncio.rst @@ -15,10 +15,10 @@ resources, running network clients and servers, and other related primitives. Here is a more detailed list of the package contents: -* a pluggable :ref:`event loop ` with various system-specific +* a pluggable :ref:`event loop ` with various system-specific implementations; -* :ref:`transport ` and :ref:`protocol ` abstractions +* :ref:`transport ` and :ref:`protocol ` abstractions (similar to those in `Twisted `_); * concrete support for TCP, UDP, SSL, subprocess pipes, delayed calls, and @@ -32,7 +32,7 @@ * cancellation support for Futures and coroutines; -* :ref:`synchronization primitives ` for use between coroutines in +* :ref:`synchronization primitives ` for use between coroutines in a single thread, mimicking those in the :mod:`threading` module; * an interface for passing work off to a threadpool, for times when -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 17:33:12 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 2 Feb 2014 17:33:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_fix_importlib?= =?utf-8?q?=2Ereload_entry=2E?= Message-ID: <3fHHlr0z3Zz7LjX@mail.python.org> http://hg.python.org/cpython/rev/a0e7e13535a7 changeset: 88894:a0e7e13535a7 user: R David Murray date: Sun Feb 02 10:50:17 2014 -0500 summary: whatsnew: fix importlib.reload entry. Turns out I committed a work-in-progress entry because of a time gap between when I wrote it and when I committed. files: Doc/whatsnew/3.4.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -765,9 +765,9 @@ it will normally be desirable to override the default implementation for performance reasons. (Contributed by Brett Cannon in :issue:`18072`.) -The :func:`~importlib.reload` function has been moved from :mod:`imp` -to :mod:`importlib`. The :func:`mod.reload` name is retained for -backward compatibility, but is deprecated. +The :func:`~importlib.reload` function has been moved from :mod:`imp` to +:mod:`importlib` as part of the :mod:`imp` module deprecation. (Contributed by +Berker Peksag in :issue:`18193`.) inspect -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 17:33:13 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 2 Feb 2014 17:33:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_filecmp=2Eclea?= =?utf-8?q?r=5Fcache=2C_and_reword_description_of_cache_in_docs=2E?= Message-ID: <3fHHls2mjtz7Ljf@mail.python.org> http://hg.python.org/cpython/rev/31b37e72b98d changeset: 88895:31b37e72b98d user: R David Murray date: Sun Feb 02 11:11:01 2014 -0500 summary: whatsnew: filecmp.clear_cache, and reword description of cache in docs. files: Doc/library/filecmp.rst | 8 ++++---- Doc/whatsnew/3.4.rst | 11 +++++++++++ Lib/filecmp.py | 4 ++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Doc/library/filecmp.rst b/Doc/library/filecmp.rst --- a/Doc/library/filecmp.rst +++ b/Doc/library/filecmp.rst @@ -28,8 +28,8 @@ portability and efficiency. This function uses a cache for past comparisons and the results, - with a cache invalidation mechanism relying on stale signatures - or by explicitly calling :func:`clear_cache`. + with cache entries invalidated if the :func:`os.stat` information for the + file changes. The entire cache may be cleared using :func:`clear_cache`. .. function:: cmpfiles(dir1, dir2, common, shallow=True) @@ -54,12 +54,12 @@ .. function:: clear_cache() - .. versionadded:: 3.4 - Clear the filecmp cache. This may be useful if a file is compared so quickly after it is modified that it is within the mtime resolution of the underlying filesystem. + .. versionadded:: 3.4 + .. _dircmp-objects: diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -675,6 +675,17 @@ (Contributed by R. David Murray in :issue:`18891`.) +filecmp +------- + +A new :func:`~filecmp.clear_cache` function provides the ability to clear the +:mod:`filecmp` comparison cache, which uses :func:`os.stat` information to +determine if the file has changed since the last compare. This can be used, +for example, if the file might have been changed and re-checked in less time +than the resolution of a particular filesystem's file modification time field. +(Contributed by Mark Levitt in :issue:`18149`.) + + functools --------- diff --git a/Lib/filecmp.py b/Lib/filecmp.py --- a/Lib/filecmp.py +++ b/Lib/filecmp.py @@ -43,8 +43,8 @@ True if the files are the same, False otherwise. This function uses a cache for past comparisons and the results, - with a cache invalidation mechanism relying on stale signatures - or by explicitly calling clear_cache(). + with cache entries invalidated if their stat information + changes. The cache may be cleared by calling clear_cache(). """ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 17:33:14 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 2 Feb 2014 17:33:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_some_more_impo?= =?utf-8?q?rtlib_replacements_for_imp_functions=2E?= Message-ID: <3fHHlt4CqGz7Lkm@mail.python.org> http://hg.python.org/cpython/rev/51b78ec2445e changeset: 88896:51b78ec2445e user: R David Murray date: Sun Feb 02 11:32:31 2014 -0500 summary: whatsnew: some more importlib replacements for imp functions. get_magic->util.MAGIC_NUMBER, source_from_cache, and cache_from_source. files: Doc/whatsnew/3.4.rst | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -761,7 +761,6 @@ of the error response. (Contributed by Karl Cow in :issue:`12921`.) - importlib --------- @@ -780,11 +779,20 @@ :mod:`importlib` as part of the :mod:`imp` module deprecation. (Contributed by Berker Peksag in :issue:`18193`.) +:mod:`importlib.util` now has a :data:`~importlib.util.MAGIC_NUMBER` attribute +providing access to the bytecode version number. This replaces the +:func:`~imp.get_magic` function in the deprecated :mod:`imp` module. +(Contributed by Brett Cannon in :issue:`18192`.) + +New :mod:`importlib.util` functions :func:`~importlib.util.cache_from_source` +and :func:`~importlib.util.source_from_cache` replace the same-named functions +in the deprecated :mod:`imp` module. (Contributed by Brett Cannon in +:issue:`18194`.) + inspect ------- - The inspect module now offers a basic :ref:`command line interface ` to quickly display source code and other information for modules, classes and functions. (Contributed by Claudiu Popa -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 18:51:35 2014 From: python-checkins at python.org (yury.selivanov) Date: Sun, 2 Feb 2014 18:51:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=2Esignature=3A_Use?= =?utf-8?q?_=27inspect=2Eisbuiltin=27_in_=27Signature=2Efrom=5Fbuiltin=27?= Message-ID: <3fHKVH16xvz7Ljf@mail.python.org> http://hg.python.org/cpython/rev/48c3c42e3e5c changeset: 88897:48c3c42e3e5c user: Yury Selivanov date: Sun Feb 02 12:51:20 2014 -0500 summary: inspect.signature: Use 'inspect.isbuiltin' in 'Signature.from_builtin' files: Lib/inspect.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1594,8 +1594,9 @@ def _signature_is_builtin(obj): # Internal helper to test if `obj` is a callable that might # support Argument Clinic's __text_signature__ protocol. - return (isinstance(obj, _NonUserDefinedCallables) or + return (isbuiltin(obj) or ismethoddescriptor(obj) or + isinstance(obj, _NonUserDefinedCallables) or # Can't test 'isinstance(type)' here, as it would # also be True for regular python classes obj in (type, object)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 18:53:15 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 2 Feb 2014 18:53:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_-m_=3Cnamespac?= =?utf-8?q?e_package=3E=2C_plus_=27using=27_doc_updates=2E?= Message-ID: <3fHKXC4rPFz7LkL@mail.python.org> http://hg.python.org/cpython/rev/28ae009435b0 changeset: 88898:28ae009435b0 user: R David Murray date: Sun Feb 02 12:19:57 2014 -0500 summary: whatsnew: -m , plus 'using' doc updates. files: Doc/using/cmdline.rst | 6 +++++- Doc/whatsnew/3.4.rst | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletions(-) diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -81,7 +81,8 @@ the implementation may not always enforce this (e.g. it may allow you to use a name that includes a hyphen). - Package names are also permitted. When a package name is supplied instead + Package names (including namespace packages) are also permitted. When a + package name is supplied instead of a normal module, the interpreter will execute ``.__main__`` as the main module. This behaviour is deliberately similar to the handling of directories and zipfiles that are passed to the interpreter as the @@ -115,6 +116,9 @@ .. versionchanged:: 3.1 Supply the package name to run a ``__main__`` submodule. + .. versionchanged:: 3.4 + namespace packages are also supported + .. describe:: - diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -789,6 +789,11 @@ in the deprecated :mod:`imp` module. (Contributed by Brett Cannon in :issue:`18194`.) +The :mod:`importlib` bootstrap :class:`.NamespaceLoader` now conforms to +the :class:`.InspectLoader` ABC, which means that ``runpy`` and +``python -m`` can now be used with namespace packages. (Contributed +by Brett Cannon in :issue:`18058`.) + inspect ------- @@ -1380,6 +1385,8 @@ :func:`sys.getallocatedblocks()`. (Contributed by Antoine Pitrou in :issue:`13390`). +* ``python -m`` now works with namespace packages. + Significant Optimizations -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 18:53:16 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 2 Feb 2014 18:53:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_hmac_accepts_m?= =?utf-8?q?ore_bytes_types=2C_importlib_decode=5Fsource=2C_stat_in_C=2E?= Message-ID: <3fHKXD6k1Cz7Ll9@mail.python.org> http://hg.python.org/cpython/rev/558b26b6a342 changeset: 88899:558b26b6a342 user: R David Murray date: Sun Feb 02 12:50:48 2014 -0500 summary: whatsnew: hmac accepts more bytes types, importlib decode_source, stat in C. files: Doc/whatsnew/3.4.rst | 18 ++++++++++++++++++ Misc/NEWS | 2 +- 2 files changed, 19 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -732,6 +732,16 @@ (Contributed by Christian Heimes in :issue:`18582`) +hmac +---- + +:mod:`hmac` now accepts ``bytearray`` as well as ``bytes`` for the *key* +argument to the :func:`~hmac.new` function, and the *msg* parameter to both the +:func:`~hmac.new` function and the :meth:`~hmac.HMAC.update` method now +accepts any type supported by the :mod:`hashlib` module. (Contributed +by Jonas Borgstr?m in :issue:`18240`.) + + html ---- @@ -794,6 +804,10 @@ ``python -m`` can now be used with namespace packages. (Contributed by Brett Cannon in :issue:`18058`.) +:mod:`importlib.util` has a new function :func:`~importlib.util.decode_source` +that decodes source from bytes using universal newline processing. This is +useful for implementing :meth:`.InspectLoader.get_source` methods. + inspect ------- @@ -1387,6 +1401,10 @@ * ``python -m`` now works with namespace packages. +* The :mod:`stat` module is now implemented in C, which means it gets the + values for its constants from the C header files, instead of having the + values hard-coded in the python module as was previously the case. + Significant Optimizations diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2346,7 +2346,7 @@ - Issue #18339: Negative ints keys in unpickler.memo dict no longer cause a segfault inside the _pickle C extension. -- Issue 18240: The HMAC module is no longer restricted to bytes and accepts +- Issue #18240: The HMAC module is no longer restricted to bytes and accepts any bytes-like object, e.g. memoryview. Original patch by Jonas Borgstr?m. - Issue #18224: Removed pydoc script from created venv, as it causes problems -- Repository URL: http://hg.python.org/cpython From rdmurray at bitdance.com Sun Feb 2 19:08:48 2014 From: rdmurray at bitdance.com (R. David Murray) Date: Sun, 02 Feb 2014 13:08:48 -0500 Subject: [Python-checkins] [Python-Dev] cpython: whatsnew: move of reload, update new windows-only ssl functions entry. In-Reply-To: References: <3fGj0k1zTdz7Llp@mail.python.org> Message-ID: <20140202180848.C8A0C250499@webabinitio.net> On Sat, 01 Feb 2014 13:20:48 -0500, Brett Cannon wrote: > On Sat, Feb 1, 2014 at 12:27 PM, r.david.murray > wrote: > > > http://hg.python.org/cpython/rev/b3f034f5000f > > changeset: 88884:b3f034f5000f > > parent: 88882:19d81cc213d7 > > user: R David Murray > > date: Sat Feb 01 12:27:07 2014 -0500 > > summary: > > whatsnew: move of reload, update new windows-only ssl functions entry. > > > > files: > > Doc/whatsnew/3.4.rst | 10 ++++++++-- > > 1 files changed, 8 insertions(+), 2 deletions(-) > > > > > > diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst > > --- a/Doc/whatsnew/3.4.rst > > +++ b/Doc/whatsnew/3.4.rst > > @@ -765,6 +765,10 @@ > > it will normally be desirable to override the default implementation > > for performance reasons. (Contributed by Brett Cannon in :issue:`18072`.) > > > > +The :func:`~importlib.reload` function has been moved from :mod:`imp` > > +to :mod:`importlib`. The :func:`mod.reload` name is retained for > > +backward compatibility, but is deprecated. > > + > > > > That wording seems confusing to me. It makes it seem like importlib.reload > is deprecated when in fact it's the imp module itself. I committed that thinking I'd finished working on that entry, but I hadn't. The updated text reads: The reload() function has been moved from imp to importlib as part of the imp module deprecation. Is that clearer? --David From brett at python.org Sun Feb 2 21:10:32 2014 From: brett at python.org (Brett Cannon) Date: Sun, 2 Feb 2014 15:10:32 -0500 Subject: [Python-checkins] [Python-Dev] cpython: whatsnew: move of reload, update new windows-only ssl functions entry. In-Reply-To: <20140202180848.C8A0C250499@webabinitio.net> References: <3fGj0k1zTdz7Llp@mail.python.org> <20140202180848.C8A0C250499@webabinitio.net> Message-ID: On Feb 2, 2014 1:08 PM, "R. David Murray" wrote: > > On Sat, 01 Feb 2014 13:20:48 -0500, Brett Cannon wrote: > > On Sat, Feb 1, 2014 at 12:27 PM, r.david.murray > > wrote: > > > > > http://hg.python.org/cpython/rev/b3f034f5000f > > > changeset: 88884:b3f034f5000f > > > parent: 88882:19d81cc213d7 > > > user: R David Murray > > > date: Sat Feb 01 12:27:07 2014 -0500 > > > summary: > > > whatsnew: move of reload, update new windows-only ssl functions entry. > > > > > > files: > > > Doc/whatsnew/3.4.rst | 10 ++++++++-- > > > 1 files changed, 8 insertions(+), 2 deletions(-) > > > > > > > > > diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst > > > --- a/Doc/whatsnew/3.4.rst > > > +++ b/Doc/whatsnew/3.4.rst > > > @@ -765,6 +765,10 @@ > > > it will normally be desirable to override the default implementation > > > for performance reasons. (Contributed by Brett Cannon in :issue:`18072`.) > > > > > > +The :func:`~importlib.reload` function has been moved from :mod:`imp` > > > +to :mod:`importlib`. The :func:`mod.reload` name is retained for > > > +backward compatibility, but is deprecated. > > > + > > > > > > > That wording seems confusing to me. It makes it seem like importlib.reload > > is deprecated when in fact it's the imp module itself. > > I committed that thinking I'd finished working on that entry, but I > hadn't. The updated text reads: > > The reload() function has been moved from imp to importlib as part > of the imp module deprecation. > > Is that clearer? Yep! And thanks for catching the missing entry. -Brett > > --David -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Sun Feb 2 21:31:25 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Feb 2014 21:31:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_use_with_state?= =?utf-8?q?ment_to_ensure_zipfile_is_always_closed_=28closes_=2320102=29?= Message-ID: <3fHP2j4kWqz7Ljb@mail.python.org> http://hg.python.org/cpython/rev/767d034b3feb changeset: 88900:767d034b3feb branch: 2.7 parent: 88890:ae1c70135763 user: Benjamin Peterson date: Sun Feb 02 15:30:22 2014 -0500 summary: use with statement to ensure zipfile is always closed (closes #20102) files: Lib/shutil.py | 20 +++++++++----------- 1 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -446,17 +446,15 @@ zip_filename, base_dir) if not dry_run: - zip = zipfile.ZipFile(zip_filename, "w", - compression=zipfile.ZIP_DEFLATED) - - for dirpath, dirnames, filenames in os.walk(base_dir): - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - if os.path.isfile(path): - zip.write(path, path) - if logger is not None: - logger.info("adding '%s'", path) - zip.close() + with zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_DEFLATED) as zf: + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + if os.path.isfile(path): + zf.write(path, path) + if logger is not None: + logger.info("adding '%s'", path) return zip_filename -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 21:31:26 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Feb 2014 21:31:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_use_with_state?= =?utf-8?q?ment_to_ensure_zipfile_is_always_closed_=28closes_=2320102=29?= Message-ID: <3fHP2k6hhkz7Lkm@mail.python.org> http://hg.python.org/cpython/rev/838674d15b5b changeset: 88901:838674d15b5b branch: 3.3 parent: 88891:412a8e2c2af6 user: Benjamin Peterson date: Sun Feb 02 15:30:22 2014 -0500 summary: use with statement to ensure zipfile is always closed (closes #20102) files: Lib/shutil.py | 20 +++++++++----------- 1 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -680,17 +680,15 @@ zip_filename, base_dir) if not dry_run: - zip = zipfile.ZipFile(zip_filename, "w", - compression=zipfile.ZIP_DEFLATED) - - for dirpath, dirnames, filenames in os.walk(base_dir): - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - if os.path.isfile(path): - zip.write(path, path) - if logger is not None: - logger.info("adding '%s'", path) - zip.close() + with zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_DEFLATED) as zf: + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + if os.path.isfile(path): + zf.write(path, path) + if logger is not None: + logger.info("adding '%s'", path) return zip_filename -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 21:31:28 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Feb 2014 21:31:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4zICgjMjAxMDIp?= Message-ID: <3fHP2m1LRpz7Llw@mail.python.org> http://hg.python.org/cpython/rev/20aa07f93ca7 changeset: 88902:20aa07f93ca7 parent: 88899:558b26b6a342 parent: 88901:838674d15b5b user: Benjamin Peterson date: Sun Feb 02 15:31:07 2014 -0500 summary: merge 3.3 (#20102) files: Lib/shutil.py | 20 +++++++++----------- 1 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -679,17 +679,15 @@ zip_filename, base_dir) if not dry_run: - zip = zipfile.ZipFile(zip_filename, "w", - compression=zipfile.ZIP_DEFLATED) - - for dirpath, dirnames, filenames in os.walk(base_dir): - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - if os.path.isfile(path): - zip.write(path, path) - if logger is not None: - logger.info("adding '%s'", path) - zip.close() + with zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_DEFLATED) as zf: + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + if os.path.isfile(path): + zf.write(path, path) + if logger is not None: + logger.info("adding '%s'", path) return zip_filename -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 22:05:41 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 2 Feb 2014 22:05:41 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE5MzIw?= =?utf-8?q?=3A_Fixed_split/splitlist_tests_in_test=5Ftcl_for_Tcl_8=2E5=2E0?= =?utf-8?b?LTguNS41Lg==?= Message-ID: <3fHPpF2ygzz7LkP@mail.python.org> http://hg.python.org/cpython/rev/515e6afd2f0f changeset: 88903:515e6afd2f0f branch: 2.7 parent: 88900:767d034b3feb user: Serhiy Storchaka date: Sun Feb 02 23:04:06 2014 +0200 summary: Issue #19320: Fixed split/splitlist tests in test_tcl for Tcl 8.5.0-8.5.5. files: Lib/test/test_tcl.py | 37 +++++++++++++++++++++++++++---- 1 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -19,6 +19,21 @@ pass tcl_version = tuple(tcl_version) +_tk_patchlevel = None +def get_tk_patchlevel(): + global _tk_patchlevel + if _tk_patchlevel is None: + tcl = Tcl() + patchlevel = [] + for x in tcl.call('info', 'patchlevel').split('.'): + try: + x = int(x, 10) + except ValueError: + x = -1 + patchlevel.append(x) + _tk_patchlevel = tuple(patchlevel) + return _tk_patchlevel + class TkinterTest(unittest.TestCase): @@ -272,10 +287,16 @@ ('1', '2', '3.4')), ] if tcl_version >= (8, 5): + if not self.wantobjects: + expected = ('12', '\xe2\x82\xac', '\xe2\x82\xac', '3.4') + elif get_tk_patchlevel() < (8, 5, 5): + # Before 8.5.5 dicts were converted to lists through string + expected = ('12', u'\u20ac', u'\u20ac', '3.4') + else: + expected = (12, u'\u20ac', u'\u20ac', (3.4,)) testcases += [ - (call('dict', 'create', 1, u'\u20ac', '\xe2\x82\xac', (3.4,)), - (1, u'\u20ac', u'\u20ac', (3.4,)) if self.wantobjects else - ('1', '\xe2\x82\xac', '\xe2\x82\xac', '3.4')), + (call('dict', 'create', 12, u'\u20ac', '\xe2\x82\xac', (3.4,)), + expected), ] for arg, res in testcases: self.assertEqual(splitlist(arg), res) @@ -312,10 +333,16 @@ ('1', '2', '3.4')), ] if tcl_version >= (8, 5): + if not self.wantobjects: + expected = ('12', '\xe2\x82\xac', '\xe2\x82\xac', '3.4') + elif get_tk_patchlevel() < (8, 5, 5): + # Before 8.5.5 dicts were converted to lists through string + expected = ('12', u'\u20ac', u'\u20ac', '3.4') + else: + expected = (12, u'\u20ac', u'\u20ac', (3.4,)) testcases += [ (call('dict', 'create', 12, u'\u20ac', '\xe2\x82\xac', (3.4,)), - (12, u'\u20ac', u'\u20ac', (3.4,)) if self.wantobjects else - ('12', '\xe2\x82\xac', '\xe2\x82\xac', '3.4')), + expected), ] for arg, res in testcases: self.assertEqual(split(arg), res) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 22:05:42 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 2 Feb 2014 22:05:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE5MzIw?= =?utf-8?q?=3A_Fixed_split/splitlist_tests_in_test=5Ftcl_for_Tcl_8=2E5=2E0?= =?utf-8?b?LTguNS41Lg==?= Message-ID: <3fHPpG4KWbz7Lly@mail.python.org> http://hg.python.org/cpython/rev/e6363a42a9f0 changeset: 88904:e6363a42a9f0 branch: 3.3 parent: 88901:838674d15b5b user: Serhiy Storchaka date: Sun Feb 02 23:04:24 2014 +0200 summary: Issue #19320: Fixed split/splitlist tests in test_tcl for Tcl 8.5.0-8.5.5. files: Lib/test/test_tcl.py | 33 +++++++++++++++++++++++++++---- 1 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -21,6 +21,21 @@ pass tcl_version = tuple(tcl_version) +_tk_patchlevel = None +def get_tk_patchlevel(): + global _tk_patchlevel + if _tk_patchlevel is None: + tcl = Tcl() + patchlevel = [] + for x in tcl.call('info', 'patchlevel').split('.'): + try: + x = int(x, 10) + except ValueError: + x = -1 + patchlevel.append(x) + _tk_patchlevel = tuple(patchlevel) + return _tk_patchlevel + class TkinterTest(unittest.TestCase): @@ -259,10 +274,14 @@ ('1', '2', '3.4')), ] if tcl_version >= (8, 5): + if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5): + # Before 8.5.5 dicts were converted to lists through string + expected = ('12', '\u20ac', '\u20ac', '3.4') + else: + expected = (12, '\u20ac', '\u20ac', (3.4,)) testcases += [ - (call('dict', 'create', 1, '\u20ac', b'\xe2\x82\xac', (3.4,)), - (1, '\u20ac', '\u20ac', (3.4,)) if self.wantobjects else - ('1', '\u20ac', '\u20ac', '3.4')), + (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)), + expected), ] for arg, res in testcases: self.assertEqual(splitlist(arg), res, msg=arg) @@ -299,10 +318,14 @@ ('1', '2', '3.4')), ] if tcl_version >= (8, 5): + if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5): + # Before 8.5.5 dicts were converted to lists through string + expected = ('12', '\u20ac', '\u20ac', '3.4') + else: + expected = (12, '\u20ac', '\u20ac', (3.4,)) testcases += [ (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)), - (12, '\u20ac', '\u20ac', (3.4,)) if self.wantobjects else - ('12', '\u20ac', '\u20ac', '3.4')), + expected), ] for arg, res in testcases: self.assertEqual(split(arg), res, msg=arg) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 22:05:43 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 2 Feb 2014 22:05:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2319320=3A_Fixed_split/splitlist_tests_in_test=5F?= =?utf-8?b?dGNsIGZvciBUY2wgOC41LjAtOC41LjUu?= Message-ID: <3fHPpH5gjSz7LmD@mail.python.org> http://hg.python.org/cpython/rev/f2fdafe73ab6 changeset: 88905:f2fdafe73ab6 parent: 88902:20aa07f93ca7 parent: 88904:e6363a42a9f0 user: Serhiy Storchaka date: Sun Feb 02 23:05:10 2014 +0200 summary: Issue #19320: Fixed split/splitlist tests in test_tcl for Tcl 8.5.0-8.5.5. files: Lib/test/test_tcl.py | 33 +++++++++++++++++++++++++++---- 1 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -21,6 +21,21 @@ pass tcl_version = tuple(tcl_version) +_tk_patchlevel = None +def get_tk_patchlevel(): + global _tk_patchlevel + if _tk_patchlevel is None: + tcl = Tcl() + patchlevel = [] + for x in tcl.call('info', 'patchlevel').split('.'): + try: + x = int(x, 10) + except ValueError: + x = -1 + patchlevel.append(x) + _tk_patchlevel = tuple(patchlevel) + return _tk_patchlevel + class TkinterTest(unittest.TestCase): @@ -259,10 +274,14 @@ ('1', '2', '3.4')), ] if tcl_version >= (8, 5): + if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5): + # Before 8.5.5 dicts were converted to lists through string + expected = ('12', '\u20ac', '\u20ac', '3.4') + else: + expected = (12, '\u20ac', '\u20ac', (3.4,)) testcases += [ - (call('dict', 'create', 1, '\u20ac', b'\xe2\x82\xac', (3.4,)), - (1, '\u20ac', '\u20ac', (3.4,)) if self.wantobjects else - ('1', '\u20ac', '\u20ac', '3.4')), + (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)), + expected), ] for arg, res in testcases: self.assertEqual(splitlist(arg), res, msg=arg) @@ -299,10 +318,14 @@ ('1', '2', '3.4')), ] if tcl_version >= (8, 5): + if not self.wantobjects or get_tk_patchlevel() < (8, 5, 5): + # Before 8.5.5 dicts were converted to lists through string + expected = ('12', '\u20ac', '\u20ac', '3.4') + else: + expected = (12, '\u20ac', '\u20ac', (3.4,)) testcases += [ (call('dict', 'create', 12, '\u20ac', b'\xe2\x82\xac', (3.4,)), - (12, '\u20ac', '\u20ac', (3.4,)) if self.wantobjects else - ('12', '\u20ac', '\u20ac', '3.4')), + expected), ] for arg, res in testcases: self.assertEqual(split(arg), res, msg=arg) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 22:44:06 2014 From: python-checkins at python.org (victor.stinner) Date: Sun, 2 Feb 2014 22:44:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_document_the_ne?= =?utf-8?q?w_asyncio=2Esubprocess_module?= Message-ID: <3fHQfZ46MCz7LjM@mail.python.org> http://hg.python.org/cpython/rev/0d3831bbc5f0 changeset: 88906:0d3831bbc5f0 user: Victor Stinner date: Sun Feb 02 22:43:39 2014 +0100 summary: asyncio: document the new asyncio.subprocess module files: Doc/library/asyncio-eventloop.rst | 5 + Doc/library/asyncio-stream.rst | 6 +- Doc/library/asyncio-subprocess.rst | 140 +++++++++++++++++ Doc/library/asyncio.rst | 1 + 4 files changed, 149 insertions(+), 3 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -353,6 +353,11 @@ This method returns a :ref:`coroutine object `. +.. seealso:: + + The :func:`create_subprocess_exec` and :func:`create_subprocess_shell` + functions. + UNIX signals ------------ diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -9,7 +9,7 @@ Stream functions ================ -.. function:: open_connection(host=None, port=None, *, loop=None, limit=_DEFAULT_LIMIT, **kwds) +.. function:: open_connection(host=None, port=None, \*, loop=None, limit=None, **kwds) A wrapper for :meth:`~BaseEventLoop.create_connection()` returning a (reader, writer) pair. @@ -32,7 +32,7 @@ This function returns a :ref:`coroutine object `. -.. function:: start_server(client_connected_cb, host=None, port=None, *, loop=None, limit=_DEFAULT_LIMIT, **kwds) +.. function:: start_server(client_connected_cb, host=None, port=None, \*, loop=None, limit=None, **kwds) Start a socket server, call back for each client connected. @@ -62,7 +62,7 @@ StreamReader ============ -.. class:: StreamReader(limit=_DEFAULT_LIMIT, loop=None) +.. class:: StreamReader(limit=None, loop=None) .. method:: exception() diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst new file mode 100644 --- /dev/null +++ b/Doc/library/asyncio-subprocess.rst @@ -0,0 +1,140 @@ +.. currentmodule:: asyncio + +Subprocess +========== + +Create a subproces +------------------ + +.. function:: create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds) + + Run the shell command *cmd* (:class:`str`)`. Return a :class:`Process` + instance. + + This function returns a :ref:`coroutine object `. + +.. function:: create_subprocess_exec(\*args, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds) + + Create a subprocess. Return a :class:`Process` instance. + + This function returns a :ref:`coroutine object `. + +Use the :meth:`BaseEventLoop.connect_read_pipe` and +:meth:`BaseEventLoop.connect_write_pipe` methods to connect pipes. + +.. seealso:: + + The :meth:`BaseEventLoop.subprocess_exec` and + :meth:`BaseEventLoop.subprocess_shell` methods. + + +Constants +--------- + +.. data:: asyncio.subprocess.PIPE + + Special value that can be used as the *stdin*, *stdout* or *stderr* argument + to :func:`create_subprocess_shell` and :func:`create_subprocess_exec` and + indicates that a pipe to the standard stream should be opened. + +.. data:: asyncio.subprocess.STDOUT + + Special value that can be used as the *stderr* argument to + :func:`create_subprocess_shell` and :func:`create_subprocess_exec` and + indicates that standard error should go into the same handle as standard + output. + +.. data:: asyncio.subprocess.DEVNULL + + Special value that can be used as the *stderr* argument to + :func:`create_subprocess_shell` and :func:`create_subprocess_exec` and + indicates that standard error should go into the same handle as standard + output. + + +Process +------- + +.. class:: asyncio.subprocess.Process + + .. attribute:: stdin + + Standard input stream (write), ``None`` if the process was created with + ``stdin=None``. + + .. attribute:: stdout + + Standard output stream (read), ``None`` if the process was created with + ``stdout=None``. + + .. attribute:: stderr + + Standard error stream (read), ``None`` if the process was created with + ``stderr=None``. + + .. attribute:: pid + + The identifier of the process. + + Note that if you set the *shell* argument to ``True``, this is the + process identifier of the spawned shell. + + .. attribute:: returncode + + Return code of the process when it exited. A ``None`` value indicates + that the process has not terminated yet. + + A negative value ``-N`` indicates that the child was terminated by signal + ``N`` (Unix only). + + .. method:: communicate(input=None) + + Interact with process: Send data to stdin. Read data from stdout and + stderr, until end-of-file is reached. Wait for process to terminate. + The optional *input* argument should be data to be sent to the child + process, or ``None``, if no data should be sent to the child. The type + of *input* must be bytes. + + :meth:`communicate` returns a tuple ``(stdoutdata, stderrdata)``. + + Note that if you want to send data to the process's stdin, you need to + create the Popen object with ``stdin=PIPE``. Similarly, to get anything + other than ``None`` in the result tuple, you need to give ``stdout=PIPE`` + and/or ``stderr=PIPE`` too. + + .. note:: + + The data read is buffered in memory, so do not use this method if the + data size is large or unlimited. + + .. method:: get_subprocess() + + Get the underlying :class:`subprocess.Popen` object. + + .. method:: kill() + + Kills the child. On Posix OSs the function sends :py:data:`SIGKILL` to + the child. On Windows :meth:`kill` is an alias for :meth:`terminate`. + + .. method:: send_signal(signale) + + Sends the signal *signal* to the child process. + + .. note:: + + On Windows, :py:data:`SIGTERM` is an alias for :meth:`terminate`. + ``CTRL_C_EVENT`` and ``CTRL_BREAK_EVENT`` can be sent to processes + started with a *creationflags* parameter which includes + ``CREATE_NEW_PROCESS_GROUP``. + + .. method:: terminate() + + Stop the child. On Posix OSs the method sends :py:data:`signal.SIGTERM` + to the child. On Windows the Win32 API function + :c:func:`TerminateProcess` is called to stop the child. + + .. method:: wait(self): + + Wait for child process to terminate. Set and return :attr:`returncode` + attribute. + diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst --- a/Doc/library/asyncio.rst +++ b/Doc/library/asyncio.rst @@ -48,6 +48,7 @@ asyncio-task.rst asyncio-protocol.rst asyncio-stream.rst + asyncio-subprocess.rst asyncio-sync.rst asyncio-dev.rst -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 22:51:53 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 2 Feb 2014 22:51:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNDIz?= =?utf-8?q?=3A_fix_documentation_of_io=2EStringIO=27s_newline_parameter?= Message-ID: <3fHQqY3zm2z7LjM@mail.python.org> http://hg.python.org/cpython/rev/82cfab2ad98d changeset: 88907:82cfab2ad98d branch: 3.3 parent: 88904:e6363a42a9f0 user: Antoine Pitrou date: Sun Feb 02 22:48:25 2014 +0100 summary: Issue #20423: fix documentation of io.StringIO's newline parameter files: Doc/library/io.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/io.rst b/Doc/library/io.rst --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -844,13 +844,14 @@ Whether line buffering is enabled. -.. class:: StringIO(initial_value='', newline=None) +.. class:: StringIO(initial_value='', newline='\\n') An in-memory stream for text I/O. The initial value of the buffer (an empty string by default) can be set by providing *initial_value*. The *newline* argument works like that of - :class:`TextIOWrapper`. The default is to do no newline translation. + :class:`TextIOWrapper`. The default is to consider only ``\n`` characters + as end of lines and to do no newline translation. :class:`StringIO` provides this method in addition to those from :class:`TextIOBase` and its parents: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 22:51:54 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 2 Feb 2014 22:51:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNDIz?= =?utf-8?q?=3A_fix_documentation_of_io=2EStringIO=27s_newline_parameter?= Message-ID: <3fHQqZ5L0yz7LlN@mail.python.org> http://hg.python.org/cpython/rev/69a2cc048c80 changeset: 88908:69a2cc048c80 branch: 2.7 parent: 88903:515e6afd2f0f user: Antoine Pitrou date: Sun Feb 02 22:48:25 2014 +0100 summary: Issue #20423: fix documentation of io.StringIO's newline parameter files: Doc/library/io.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/io.rst b/Doc/library/io.rst --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -791,14 +791,14 @@ Whether line buffering is enabled. -.. class:: StringIO(initial_value=u'', newline=None) +.. class:: StringIO(initial_value=u'', newline=u'\\n') An in-memory stream for unicode text. It inherits :class:`TextIOWrapper`. The initial value of the buffer (an empty unicode string by default) can be set by providing *initial_value*. The *newline* argument works like - that of :class:`TextIOWrapper`. The default is to do no newline - translation. + that of :class:`TextIOWrapper`. The default is to consider only ``\n`` + characters as end of lines and to do no newline translation. :class:`StringIO` provides this method in addition to those from :class:`TextIOWrapper` and its parents: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 22:51:55 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 2 Feb 2014 22:51:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320423=3A_fix_documentation_of_io=2EStringIO=27s?= =?utf-8?q?_newline_parameter?= Message-ID: <3fHQqb6h6vz7Ll2@mail.python.org> http://hg.python.org/cpython/rev/df2efd48227e changeset: 88909:df2efd48227e parent: 88906:0d3831bbc5f0 parent: 88907:82cfab2ad98d user: Antoine Pitrou date: Sun Feb 02 22:49:03 2014 +0100 summary: Issue #20423: fix documentation of io.StringIO's newline parameter files: Doc/library/io.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/io.rst b/Doc/library/io.rst --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -849,13 +849,14 @@ Whether line buffering is enabled. -.. class:: StringIO(initial_value='', newline=None) +.. class:: StringIO(initial_value='', newline='\\n') An in-memory stream for text I/O. The initial value of the buffer (an empty string by default) can be set by providing *initial_value*. The *newline* argument works like that of - :class:`TextIOWrapper`. The default is to do no newline translation. + :class:`TextIOWrapper`. The default is to consider only ``\n`` characters + as end of lines and to do no newline translation. :class:`StringIO` provides this method in addition to those from :class:`TextIOBase` and its parents: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 23:01:29 2014 From: python-checkins at python.org (ned.deily) Date: Sun, 2 Feb 2014 23:01:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE5OTkw?= =?utf-8?q?=3A_Install_test/imghdrdata=2E?= Message-ID: <3fHR2d15Sgz7LjM@mail.python.org> http://hg.python.org/cpython/rev/e2d013e90e88 changeset: 88910:e2d013e90e88 branch: 2.7 parent: 88908:69a2cc048c80 user: Ned Deily date: Sun Feb 02 13:59:26 2014 -0800 summary: Issue #19990: Install test/imghdrdata. files: Makefile.pre.in | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -931,7 +931,9 @@ PLATMACPATH=:plat-mac:plat-mac/lib-scriptpackages LIBSUBDIRS= lib-tk lib-tk/test lib-tk/test/test_tkinter \ lib-tk/test/test_ttk site-packages test test/audiodata test/data \ - test/cjkencodings test/decimaltestdata test/xmltestdata test/subprocessdata \ + test/cjkencodings test/decimaltestdata test/xmltestdata \ + test/imghdrdata \ + test/subprocessdata \ test/tracedmodules \ encodings compiler hotshot \ email email/mime email/test email/test/data \ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 23:01:30 2014 From: python-checkins at python.org (ned.deily) Date: Sun, 2 Feb 2014 23:01:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE5OTkw?= =?utf-8?q?=3A_Install_test/imghdrdata=2E?= Message-ID: <3fHR2f2vTtz7LjM@mail.python.org> http://hg.python.org/cpython/rev/5fbe155e62b0 changeset: 88911:5fbe155e62b0 branch: 3.3 parent: 88907:82cfab2ad98d user: Ned Deily date: Sun Feb 02 13:59:49 2014 -0800 summary: Issue #19990: Install test/imghdrdata. files: Makefile.pre.in | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1019,6 +1019,7 @@ test/audiodata \ test/capath test/data \ test/cjkencodings test/decimaltestdata test/xmltestdata \ + test/imghdrdata \ test/subprocessdata test/sndhdrdata test/support \ test/tracedmodules test/encoded_modules \ test/namespace_pkgs \ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 23:01:31 2014 From: python-checkins at python.org (ned.deily) Date: Sun, 2 Feb 2014 23:01:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2319990=3A_Install_test/imghdrdata=2E?= Message-ID: <3fHR2g4dv8z7LjX@mail.python.org> http://hg.python.org/cpython/rev/b41ba99a276c changeset: 88912:b41ba99a276c parent: 88909:df2efd48227e parent: 88911:5fbe155e62b0 user: Ned Deily date: Sun Feb 02 14:00:39 2014 -0800 summary: Issue #19990: Install test/imghdrdata. files: Makefile.pre.in | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1116,6 +1116,7 @@ test/audiodata \ test/capath test/data \ test/cjkencodings test/decimaltestdata test/xmltestdata \ + test/imghdrdata \ test/subprocessdata test/sndhdrdata test/support \ test/tracedmodules test/encoded_modules \ test/namespace_pkgs \ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 23:40:57 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 2 Feb 2014 23:40:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNDM1?= =?utf-8?q?=3A_Fix_=5Fpyio=2EStringIO=2Egetvalue=28=29_to_take_into_accoun?= =?utf-8?q?t_newline?= Message-ID: <3fHRw93Nyhz7LkG@mail.python.org> http://hg.python.org/cpython/rev/99168e7d4a3d changeset: 88913:99168e7d4a3d branch: 3.3 parent: 88911:5fbe155e62b0 user: Antoine Pitrou date: Sun Feb 02 23:37:29 2014 +0100 summary: Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline translation settings. files: Lib/_pyio.py | 8 +++++++- Lib/test/test_memoryio.py | 9 +++++++++ Misc/NEWS | 3 +++ 3 files changed, 19 insertions(+), 1 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -2060,7 +2060,13 @@ def getvalue(self): self.flush() - return self.buffer.getvalue().decode(self._encoding, self._errors) + decoder = self._decoder or self._get_decoder() + old_state = decoder.getstate() + decoder.reset() + try: + return decoder.decode(self.buffer.getvalue(), final=True) + finally: + decoder.setstate(old_state) def __repr__(self): # TextIOWrapper tells the encoding in its repr. In StringIO, diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -551,6 +551,7 @@ self.assertEqual(3, memio.write("c\rd")) memio.seek(0) self.assertEqual(memio.read(), "a\nb\nc\nd") + self.assertEqual(memio.getvalue(), "a\nb\nc\nd") memio = self.ioclass("a\r\nb", newline=None) self.assertEqual(memio.read(3), "a\nb") @@ -562,6 +563,7 @@ self.assertEqual(memio.read(4), "a\nb\r") self.assertEqual(memio.read(2), "\nc") self.assertEqual(memio.read(1), "\r") + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") memio = self.ioclass(newline="") self.assertEqual(2, memio.write("a\n")) self.assertEqual(2, memio.write("b\r")) @@ -581,6 +583,9 @@ self.assertEqual(memio.read(), "a\rb\r\rc\rd") memio.seek(0) self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"]) + memio.seek(0) + self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"]) + self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd") def test_newline_crlf(self): # newline="\r\n" @@ -588,11 +593,15 @@ self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd") memio.seek(0) self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"]) + memio.seek(0) + self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd") def test_issue5265(self): # StringIO can duplicate newlines in universal newlines mode memio = self.ioclass("a\r\nb\r\n", newline=None) self.assertEqual(memio.read(5), "a\nb\n") + self.assertEqual(memio.getvalue(), "a\nb\n") def test_newline_argument(self): self.assertRaises(TypeError, self.ioclass, newline=b"\n") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,9 @@ Library ------- +- Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline + translation settings. + - Issue #20288: fix handling of invalid numeric charrefs in HTMLParser. - Issue #20424: Python implementation of io.StringIO now supports lone surrogates. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 23:40:58 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 2 Feb 2014 23:40:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogSXNzdWUgIzIwNDM1OiBGaXggX3B5aW8uU3RyaW5nSU8uZ2V0dmFsdWUo?= =?utf-8?q?=29_to_take_into_account_newline?= Message-ID: <3fHRwB51j8z7LlG@mail.python.org> http://hg.python.org/cpython/rev/aadcc71a4967 changeset: 88914:aadcc71a4967 parent: 88912:b41ba99a276c parent: 88913:99168e7d4a3d user: Antoine Pitrou date: Sun Feb 02 23:38:48 2014 +0100 summary: Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline translation settings. files: Lib/_pyio.py | 8 +++++++- Lib/test/test_memoryio.py | 9 +++++++++ Misc/NEWS | 3 +++ 3 files changed, 19 insertions(+), 1 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -2067,7 +2067,13 @@ def getvalue(self): self.flush() - return self.buffer.getvalue().decode(self._encoding, self._errors) + decoder = self._decoder or self._get_decoder() + old_state = decoder.getstate() + decoder.reset() + try: + return decoder.decode(self.buffer.getvalue(), final=True) + finally: + decoder.setstate(old_state) def __repr__(self): # TextIOWrapper tells the encoding in its repr. In StringIO, diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -551,6 +551,7 @@ self.assertEqual(3, memio.write("c\rd")) memio.seek(0) self.assertEqual(memio.read(), "a\nb\nc\nd") + self.assertEqual(memio.getvalue(), "a\nb\nc\nd") memio = self.ioclass("a\r\nb", newline=None) self.assertEqual(memio.read(3), "a\nb") @@ -562,6 +563,7 @@ self.assertEqual(memio.read(4), "a\nb\r") self.assertEqual(memio.read(2), "\nc") self.assertEqual(memio.read(1), "\r") + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") memio = self.ioclass(newline="") self.assertEqual(2, memio.write("a\n")) self.assertEqual(2, memio.write("b\r")) @@ -581,6 +583,9 @@ self.assertEqual(memio.read(), "a\rb\r\rc\rd") memio.seek(0) self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"]) + memio.seek(0) + self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"]) + self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd") def test_newline_crlf(self): # newline="\r\n" @@ -588,11 +593,15 @@ self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd") memio.seek(0) self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"]) + memio.seek(0) + self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd") def test_issue5265(self): # StringIO can duplicate newlines in universal newlines mode memio = self.ioclass("a\r\nb\r\n", newline=None) self.assertEqual(memio.read(5), "a\nb\n") + self.assertEqual(memio.getvalue(), "a\nb\n") def test_newline_argument(self): self.assertRaises(TypeError, self.ioclass, newline=b"\n") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,9 @@ Library ------- +- Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline + translation settings. + - tracemalloc: Fix slicing traces and fix slicing a traceback. - Issue #20354: Fix an alignment issue in the tracemalloc module on 64-bit -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 2 23:42:04 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 2 Feb 2014 23:42:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNDM1?= =?utf-8?q?=3A_Fix_=5Fpyio=2EStringIO=2Egetvalue=28=29_to_take_into_accoun?= =?utf-8?q?t_newline?= Message-ID: <3fHRxS6ySSz7LkG@mail.python.org> http://hg.python.org/cpython/rev/3e61d8e06ef7 changeset: 88915:3e61d8e06ef7 branch: 2.7 parent: 88910:e2d013e90e88 user: Antoine Pitrou date: Sun Feb 02 23:37:29 2014 +0100 summary: Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline translation settings. files: Lib/_pyio.py | 8 +++++++- Lib/test/test_memoryio.py | 9 +++++++++ Misc/NEWS | 3 +++ 3 files changed, 19 insertions(+), 1 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -1997,7 +1997,13 @@ def getvalue(self): self.flush() - return self.buffer.getvalue().decode(self._encoding, self._errors) + decoder = self._decoder or self._get_decoder() + old_state = decoder.getstate() + decoder.reset() + try: + return decoder.decode(self.buffer.getvalue(), final=True) + finally: + decoder.setstate(old_state) def __repr__(self): # TextIOWrapper tells the encoding in its repr. In StringIO, diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -537,6 +537,7 @@ self.assertEqual(3, memio.write("c\rd")) memio.seek(0) self.assertEqual(memio.read(), "a\nb\nc\nd") + self.assertEqual(memio.getvalue(), "a\nb\nc\nd") memio = self.ioclass("a\r\nb", newline=None) self.assertEqual(memio.read(3), "a\nb") @@ -548,6 +549,7 @@ self.assertEqual(memio.read(4), "a\nb\r") self.assertEqual(memio.read(2), "\nc") self.assertEqual(memio.read(1), "\r") + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") memio = self.ioclass(newline="") self.assertEqual(2, memio.write("a\n")) self.assertEqual(2, memio.write("b\r")) @@ -567,6 +569,9 @@ self.assertEqual(memio.read(), "a\rb\r\rc\rd") memio.seek(0) self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"]) + memio.seek(0) + self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"]) + self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd") def test_newline_crlf(self): # newline="\r\n" @@ -574,11 +579,15 @@ self.assertEqual(memio.read(), "a\r\nb\r\r\nc\rd") memio.seek(0) self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"]) + memio.seek(0) + self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd") def test_issue5265(self): # StringIO can duplicate newlines in universal newlines mode memio = self.ioclass("a\r\nb\r\n", newline=None) self.assertEqual(memio.read(5), "a\nb\n") + self.assertEqual(memio.getvalue(), "a\nb\n") class PyStringIOTest(MemoryTestMixin, MemorySeekTestMixin, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -38,6 +38,9 @@ Library ------- +- Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline + translation settings. + - Issue #20288: fix handling of invalid numeric charrefs in HTMLParser. - Issue #19456: ntpath.join() now joins relative paths correctly when a drive -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 00:37:21 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 3 Feb 2014 00:37:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320472=3A_test=5Fa?= =?utf-8?q?syncio=3A_skip_PTY_tests_on_Mac_OS_X_older_than_10=2E6?= Message-ID: <3fHT9F3C54z7Ljf@mail.python.org> http://hg.python.org/cpython/rev/21a4ebf5a170 changeset: 88916:21a4ebf5a170 parent: 88914:aadcc71a4967 user: Victor Stinner date: Mon Feb 03 00:32:13 2014 +0100 summary: Issue #20472: test_asyncio: skip PTY tests on Mac OS X older than 10.6 files: Lib/test/test_asyncio/test_events.py | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -953,6 +953,9 @@ @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) def test_read_pty_output(self): proto = None @@ -1075,6 +1078,9 @@ @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) def test_write_pty(self): proto = None transport = None -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 00:37:22 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 3 Feb 2014 00:37:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320472=3A_asyncio?= =?utf-8?q?=3A_Adjust_the_note_about_Mac_OS_X_on_PTY=2C_specify_that_it?= Message-ID: <3fHT9G4jTYz7LkD@mail.python.org> http://hg.python.org/cpython/rev/0a71d29b970a changeset: 88917:0a71d29b970a user: Victor Stinner date: Mon Feb 03 00:35:46 2014 +0100 summary: Issue #20472: asyncio: Adjust the note about Mac OS X on PTY, specify that it requires at least Mac OS X 10.6. files: Doc/library/asyncio-eventloop.rst | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -313,7 +313,8 @@ On Mac OS X older than 10.9 (Mavericks), :class:`selectors.KqueueSelector` does not support character devices like PTY, whereas it is used by the default event loop. The :class:`SelectorEventLoop` can be used with - :class:`SelectSelector` to handle character devices. + :class:`SelectSelector` or :class:`PollSelector` to handle character devices + on Mac OS X 10.6 (Snow Leopard) and later. .. method:: BaseEventLoop.subprocess_exec(protocol_factory, \*args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=False, shell=False, bufsize=0, \*\*kwargs) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 07:33:53 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 3 Feb 2014 07:33:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_html=2Eescape_?= =?utf-8?q?10x_faster=2C_=5Fgestalt_module_gone=2E?= Message-ID: <3fHfPs6Gfmz7Lk7@mail.python.org> http://hg.python.org/cpython/rev/c2a21098fe7f changeset: 88918:c2a21098fe7f user: R David Murray date: Mon Feb 03 01:14:03 2014 -0500 summary: whatsnew: html.escape 10x faster, _gestalt module gone. files: Doc/whatsnew/3.4.rst | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1448,6 +1448,8 @@ significant amounts of data through :mod:`subprocess`. (Contributed by Richard Oudkerk in :issue:`15758`.) +* :func:`html.escape` is now 10x faster. (Contributed by Matt Bryant in + :issue:`18020`.) Deprecated @@ -1559,6 +1561,11 @@ * The unused and undocumented internal ``Scanner`` class has been removed from the :mod:`pydoc` module. +* The private and effectively unused ``_gestalt`` module has been removed, + along with the private :mod:`platform` functions ``_mac_ver_lookup``, + ``_mac_ver_gstalt``, and ``_bcd2str``, which would only have ever been called + on badly broken OSX systems (see :issue:`18393`). + Porting to Python 3.4 @@ -1608,7 +1615,7 @@ exceptions now. * :func:`functools.update_wrapper` and :func:`functools.wraps` now correctly - set the ``__wrapped__`` attribute to the function being wrapper, even if + set the ``__wrapped__`` attribute to the function being wrapped, even if that function also had its ``__wrapped__`` attribute set. This means ``__wrapped__`` attributes now correctly link a stack of decorated functions rather than every ``__wrapped__`` attribute in the chain -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 07:33:55 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 3 Feb 2014 07:33:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_read/write_on_?= =?utf-8?q?closed_SSL_socket_exception_has_changed=2E?= Message-ID: <3fHfPv0sLZz7Lm8@mail.python.org> http://hg.python.org/cpython/rev/33bfe77aca56 changeset: 88919:33bfe77aca56 user: R David Murray date: Mon Feb 03 01:33:39 2014 -0500 summary: whatsnew: read/write on closed SSL socket exception has changed. files: Doc/whatsnew/3.4.rst | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -543,6 +543,7 @@ The number of digits in the coefficients for the RGB --- YIQ conversions have been expanded so that they match the FCC NTSC versions. The change in results should be less than 1% and may better match results found elsewhere. +(Contributed by Brian Landers and Serhiy Storchaka in :issue:`14323`.) contextlib @@ -694,7 +695,6 @@ for normal callables. The new descriptor also makes it easier to get arbitrary callables (including :func:`~functools.partial` instances) to behave like normal instance methods when included in a class definition. - (Contributed by Alon Horev and Nick Coghlan in :issue:`4331`) .. _whatsnew-singledispatch: @@ -1665,6 +1665,10 @@ entire :class:`cgi.FieldStorage` instance or read the contents of the file before the :class:`cgi.FieldStorage` instance is garbage collected. +* Calling ``read`` or ``write`` on a closed SSL socket now raises an + informative :exc:`ValueError` rather than the previous more mysterious + :exc:`AttributeError` (:issue:`9177`). + Changes in the C API -------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 08:48:26 2014 From: python-checkins at python.org (yury.selivanov) Date: Mon, 3 Feb 2014 08:48:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=2Esignature=3A_Add?= =?utf-8?q?_=28restore=29_support_for_builtin_classes_=2320473?= Message-ID: <3fHh3t5bj2z7LkN@mail.python.org> http://hg.python.org/cpython/rev/c19f5e4fdbe0 changeset: 88920:c19f5e4fdbe0 user: Yury Selivanov date: Mon Feb 03 02:46:07 2014 -0500 summary: inspect.signature: Add (restore) support for builtin classes #20473 files: Lib/inspect.py | 295 +++++++++++++++----------- Lib/test/test_inspect.py | 26 ++ 2 files changed, 190 insertions(+), 131 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1648,6 +1648,139 @@ return spec[2:pos] +def _signature_fromstr(cls, obj, s): + # Internal helper to parse content of '__text_signature__' + # and return a Signature based on it + Parameter = cls._parameter_cls + + if s.endswith("/)"): + kind = Parameter.POSITIONAL_ONLY + s = s[:-2] + ')' + else: + kind = Parameter.POSITIONAL_OR_KEYWORD + + first_parameter_is_self = s.startswith("($") + if first_parameter_is_self: + s = '(' + s[2:] + + s = "def foo" + s + ": pass" + + try: + module = ast.parse(s) + except SyntaxError: + module = None + + if not isinstance(module, ast.Module): + raise ValueError("{!r} builtin has invalid signature".format(obj)) + + f = module.body[0] + + parameters = [] + empty = Parameter.empty + invalid = object() + + module = None + module_dict = {} + module_name = getattr(obj, '__module__', None) + if module_name: + module = sys.modules.get(module_name, None) + if module: + module_dict = module.__dict__ + sys_module_dict = sys.modules + + def parse_name(node): + assert isinstance(node, ast.arg) + if node.annotation != None: + raise ValueError("Annotations are not currently supported") + return node.arg + + def wrap_value(s): + try: + value = eval(s, module_dict) + except NameError: + try: + value = eval(s, sys_module_dict) + except NameError: + raise RuntimeError() + + if isinstance(value, str): + return ast.Str(value) + if isinstance(value, (int, float)): + return ast.Num(value) + if isinstance(value, bytes): + return ast.Bytes(value) + if value in (True, False, None): + return ast.NameConstant(value) + raise RuntimeError() + + class RewriteSymbolics(ast.NodeTransformer): + def visit_Attribute(self, node): + a = [] + n = node + while isinstance(n, ast.Attribute): + a.append(n.attr) + n = n.value + if not isinstance(n, ast.Name): + raise RuntimeError() + a.append(n.id) + value = ".".join(reversed(a)) + return wrap_value(value) + + def visit_Name(self, node): + if not isinstance(node.ctx, ast.Load): + raise ValueError() + return wrap_value(node.id) + + def p(name_node, default_node, default=empty): + name = parse_name(name_node) + if name is invalid: + return None + if default_node and default_node is not _empty: + try: + default_node = RewriteSymbolics().visit(default_node) + o = ast.literal_eval(default_node) + except ValueError: + o = invalid + if o is invalid: + return None + default = o if o is not invalid else default + parameters.append(Parameter(name, kind, default=default, annotation=empty)) + + # non-keyword-only parameters + args = reversed(f.args.args) + defaults = reversed(f.args.defaults) + iter = itertools.zip_longest(args, defaults, fillvalue=None) + for name, default in reversed(list(iter)): + p(name, default) + + # *args + if f.args.vararg: + kind = Parameter.VAR_POSITIONAL + p(f.args.vararg, empty) + + # keyword-only arguments + kind = Parameter.KEYWORD_ONLY + for name, default in zip(f.args.kwonlyargs, f.args.kw_defaults): + p(name, default) + + # **kwargs + if f.args.kwarg: + kind = Parameter.VAR_KEYWORD + p(f.args.kwarg, empty) + + if first_parameter_is_self: + assert parameters + if getattr(obj, '__self__', None): + # strip off self, it's already been bound + parameters.pop(0) + else: + # for builtins, self parameter is always positional-only! + p = parameters[0].replace(kind=Parameter.POSITIONAL_ONLY) + parameters[0] = p + + return cls(parameters, return_annotation=cls.empty) + + def signature(obj): '''Get a signature object for the passed callable.''' @@ -1725,14 +1858,41 @@ sig = signature(init) if sig is None: + # At this point we know, that `obj` is a class, with no user- + # defined '__init__', '__new__', or class-level '__call__' + + for base in obj.__mro__: + # Since '__text_signature__' is implemented as a + # descriptor that extracts text signature from the + # class docstring, if 'obj' is derived from a builtin + # class, its own '__text_signature__' may be 'None'. + # Therefore, we go through the MRO to find the first + # class with non-empty text signature. + try: + text_sig = base.__text_signature__ + except AttributeError: + pass + else: + if text_sig: + # If 'obj' class has a __text_signature__ attribute: + # return a signature based on it + return _signature_fromstr(Signature, obj, text_sig) + + # No '__text_signature__' was found for the 'obj' class. + # Last option is to check if its '__init__' is + # object.__init__ or type.__init__. if type in obj.__mro__: # 'obj' is a metaclass without user-defined __init__ - # or __new__. Return a signature of 'type' builtin. - return signature(type) + # or __new__. + if obj.__init__ is type.__init__: + # Return a signature of 'type' builtin. + return signature(type) else: # We have a class (not metaclass), but no user-defined # __init__ or __new__ for it - return signature(object) + if obj.__init__ is object.__init__: + # Return a signature of 'object' builtin. + return signature(object) elif not isinstance(obj, _NonUserDefinedCallables): # An object with __call__ @@ -2196,134 +2356,7 @@ if not s: raise ValueError("no signature found for builtin {!r}".format(func)) - Parameter = cls._parameter_cls - - if s.endswith("/)"): - kind = Parameter.POSITIONAL_ONLY - s = s[:-2] + ')' - else: - kind = Parameter.POSITIONAL_OR_KEYWORD - - first_parameter_is_self = s.startswith("($") - if first_parameter_is_self: - s = '(' + s[2:] - - s = "def foo" + s + ": pass" - - try: - module = ast.parse(s) - except SyntaxError: - module = None - - if not isinstance(module, ast.Module): - raise ValueError("{!r} builtin has invalid signature".format(func)) - - f = module.body[0] - - parameters = [] - empty = Parameter.empty - invalid = object() - - module = None - module_dict = {} - module_name = getattr(func, '__module__', None) - if module_name: - module = sys.modules.get(module_name, None) - if module: - module_dict = module.__dict__ - sys_module_dict = sys.modules - - def parse_name(node): - assert isinstance(node, ast.arg) - if node.annotation != None: - raise ValueError("Annotations are not currently supported") - return node.arg - - def wrap_value(s): - try: - value = eval(s, module_dict) - except NameError: - try: - value = eval(s, sys_module_dict) - except NameError: - raise RuntimeError() - - if isinstance(value, str): - return ast.Str(value) - if isinstance(value, (int, float)): - return ast.Num(value) - if isinstance(value, bytes): - return ast.Bytes(value) - if value in (True, False, None): - return ast.NameConstant(value) - raise RuntimeError() - - class RewriteSymbolics(ast.NodeTransformer): - def visit_Attribute(self, node): - a = [] - n = node - while isinstance(n, ast.Attribute): - a.append(n.attr) - n = n.value - if not isinstance(n, ast.Name): - raise RuntimeError() - a.append(n.id) - value = ".".join(reversed(a)) - return wrap_value(value) - - def visit_Name(self, node): - if not isinstance(node.ctx, ast.Load): - raise ValueError() - return wrap_value(node.id) - - def p(name_node, default_node, default=empty): - name = parse_name(name_node) - if name is invalid: - return None - if default_node and default_node is not _empty: - try: - default_node = RewriteSymbolics().visit(default_node) - o = ast.literal_eval(default_node) - except ValueError: - o = invalid - if o is invalid: - return None - default = o if o is not invalid else default - parameters.append(Parameter(name, kind, default=default, annotation=empty)) - - # non-keyword-only parameters - args = reversed(f.args.args) - defaults = reversed(f.args.defaults) - iter = itertools.zip_longest(args, defaults, fillvalue=None) - for name, default in reversed(list(iter)): - p(name, default) - - # *args - if f.args.vararg: - kind = Parameter.VAR_POSITIONAL - p(f.args.vararg, empty) - - # keyword-only arguments - kind = Parameter.KEYWORD_ONLY - for name, default in zip(f.args.kwonlyargs, f.args.kw_defaults): - p(name, default) - - # **kwargs - if f.args.kwarg: - kind = Parameter.VAR_KEYWORD - p(f.args.kwarg, empty) - - if first_parameter_is_self: - assert parameters - if getattr(func, '__self__', None): - # strip off self, it's already been bound - parameters.pop(0) - else: - # for builtins, self parameter is always positional-only! - p = parameters[0].replace(kind=Parameter.POSITIONAL_ONLY) - parameters[0] = p - - return cls(parameters, return_annotation=cls.empty) + return _signature_fromstr(cls, func, s) @property def parameters(self): diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -2210,6 +2210,32 @@ self.assertEqual(str(inspect.signature(D)), '(object_or_name, bases, dict)') + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") + def test_signature_on_builtin_class(self): + self.assertEqual(str(inspect.signature(_pickle.Pickler)), + '(file, protocol=None, fix_imports=True)') + + class P(_pickle.Pickler): pass + class EmptyTrait: pass + class P2(EmptyTrait, P): pass + self.assertEqual(str(inspect.signature(P)), + '(file, protocol=None, fix_imports=True)') + self.assertEqual(str(inspect.signature(P2)), + '(file, protocol=None, fix_imports=True)') + + class P3(P2): + def __init__(self, spam): + pass + self.assertEqual(str(inspect.signature(P3)), '(spam)') + + class MetaP(type): + def __call__(cls, foo, bar): + pass + class P4(P2, metaclass=MetaP): + pass + self.assertEqual(str(inspect.signature(P4)), '(foo, bar)') + def test_signature_on_callable_objects(self): class Foo: def __call__(self, a): -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Feb 3 09:41:39 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 03 Feb 2014 09:41:39 +0100 Subject: [Python-checkins] Daily reference leaks (0a71d29b970a): sum=4 Message-ID: results for 0a71d29b970a on branch "default" -------------------------------------------- test__opcode leaked [3, 3, 3] references, sum=9 test_site leaked [0, 0, 2] references, sum=2 test_site leaked [0, 0, 2] memory blocks, sum=2 test_urllib2net leaked [1590, -1601, 0] references, sum=-11 test_urllib2net leaked [1409, -1409, 2] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogJggTYV', '-x'] From python-checkins at python.org Mon Feb 3 12:52:39 2014 From: python-checkins at python.org (vinay.sajip) Date: Mon, 3 Feb 2014 12:52:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Added_cookbook?= =?utf-8?q?_entry_on_logging_filter_configuration_using_dictConfig=28=29?= =?utf-8?q?=2E?= Message-ID: <3fHnTg3xjHz7LjP@mail.python.org> http://hg.python.org/cpython/rev/ae7facd874ba changeset: 88921:ae7facd874ba branch: 2.7 parent: 88915:3e61d8e06ef7 user: Vinay Sajip date: Mon Feb 03 11:51:22 2014 +0000 summary: Added cookbook entry on logging filter configuration using dictConfig(). files: Doc/howto/logging-cookbook.rst | 220 +++++++++++++++++++++ 1 files changed, 220 insertions(+), 0 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -834,3 +834,223 @@ Note that the order of items might be different according to the version of Python used. + + +.. _custom-handlers: + +.. currentmodule:: logging.config + +Customizing handlers with :func:`dictConfig` +-------------------------------------------- + +There are times when you want to customize logging handlers in particular ways, +and if you use :func:`dictConfig` you may be able to do this without +subclassing. As an example, consider that you may want to set the ownership of a +log file. On POSIX, this is easily done using :func:`shutil.chown`, but the file +handlers in the stdlib don't offer built-in support. You can customize handler +creation using a plain function such as:: + + def owned_file_handler(filename, mode='a', encoding=None, owner=None): + if owner: + if not os.path.exists(filename): + open(filename, 'a').close() + shutil.chown(filename, *owner) + return logging.FileHandler(filename, mode, encoding) + +You can then specify, in a logging configuration passed to :func:`dictConfig`, +that a logging handler be created by calling this function:: + + LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'default': { + 'format': '%(asctime)s %(levelname)s %(name)s %(message)s' + }, + }, + 'handlers': { + 'file':{ + # The values below are popped from this dictionary and + # used to create the handler, set the handler's level and + # its formatter. + '()': owned_file_handler, + 'level':'DEBUG', + 'formatter': 'default', + # The values below are passed to the handler creator callable + # as keyword arguments. + 'owner': ['pulse', 'pulse'], + 'filename': 'chowntest.log', + 'mode': 'w', + 'encoding': 'utf-8', + }, + }, + 'root': { + 'handlers': ['file'], + 'level': 'DEBUG', + }, + } + +In this example I am setting the ownership using the ``pulse`` user and group, +just for the purposes of illustration. Putting it together into a working +script, ``chowntest.py``:: + + import logging, logging.config, os, shutil + + def owned_file_handler(filename, mode='a', encoding=None, owner=None): + if owner: + if not os.path.exists(filename): + open(filename, 'a').close() + shutil.chown(filename, *owner) + return logging.FileHandler(filename, mode, encoding) + + LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'default': { + 'format': '%(asctime)s %(levelname)s %(name)s %(message)s' + }, + }, + 'handlers': { + 'file':{ + # The values below are popped from this dictionary and + # used to create the handler, set the handler's level and + # its formatter. + '()': owned_file_handler, + 'level':'DEBUG', + 'formatter': 'default', + # The values below are passed to the handler creator callable + # as keyword arguments. + 'owner': ['pulse', 'pulse'], + 'filename': 'chowntest.log', + 'mode': 'w', + 'encoding': 'utf-8', + }, + }, + 'root': { + 'handlers': ['file'], + 'level': 'DEBUG', + }, + } + + logging.config.dictConfig(LOGGING) + logger = logging.getLogger('mylogger') + logger.debug('A debug message') + +To run this, you will probably need to run as ``root``:: + + $ sudo python3.3 chowntest.py + $ cat chowntest.log + 2013-11-05 09:34:51,128 DEBUG mylogger A debug message + $ ls -l chowntest.log + -rw-r--r-- 1 pulse pulse 55 2013-11-05 09:34 chowntest.log + +Note that this example uses Python 3.3 because that's where :func:`shutil.chown` +makes an appearance. This approach should work with any Python version that +supports :func:`dictConfig` - namely, Python 2.7, 3.2 or later. With pre-3.3 +versions, you would need to implement the actual ownership change using e.g. +:func:`os.chown`. + +In practice, the handler-creating function may be in a utility module somewhere +in your project. Instead of the line in the configuration:: + + '()': owned_file_handler, + +you could use e.g.:: + + '()': 'ext://project.util.owned_file_handler', + +where ``project.util`` can be replaced with the actual name of the package +where the function resides. In the above working script, using +``'ext://__main__.owned_file_handler'`` should work. Here, the actual callable +is resolved by :func:`dictConfig` from the ``ext://`` specification. + +This example hopefully also points the way to how you could implement other +types of file change - e.g. setting specific POSIX permission bits - in the +same way, using :func:`os.chmod`. + +Of course, the approach could also be extended to types of handler other than a +:class:`~logging.FileHandler` - for example, one of the rotating file handlers, +or a different type of handler altogether. + + +.. _filters-dictconfig: + +Configuring filters with :func:`dictConfig` +------------------------------------------- + +You *can* configure filters using :func:`~logging.config.dictConfig`, though it +might not be obvious at first glance how to do it (hence this recipe). Since +:class:`~logging.Filter` is the only filter class included in the standard +library, and it is unlikely to cater to many requirements (it's only there as a +base class), you will typically need to define your own :class:`~logging.Filter` +subclass with an overridden :meth:`~logging.Filter.filter` method. To do this, +specify the ``()`` key in the configuration dictionary for the filter, +specifying a callable which will be used to create the filter (a class is the +most obvious, but you can provide any callable which returns a +:class:`~logging.Filter` instance). Here is a complete example:: + + import logging + import logging.config + import sys + + class MyFilter(logging.Filter): + def __init__(self, param=None): + self.param = param + + def filter(self, record): + if self.param is None: + allow = True + else: + allow = self.param not in record.msg + if allow: + record.msg = 'changed: ' + record.msg + return allow + + LOGGING = { + 'version': 1, + 'filters': { + 'myfilter': { + '()': MyFilter, + 'param': 'noshow', + } + }, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'filters': ['myfilter'] + } + }, + 'root': { + 'level': 'DEBUG', + 'handlers': ['console'] + }, + } + + if __name__ == '__main__': + logging.config.dictConfig(LOGGING) + logging.debug('hello') + logging.debug('hello - noshow') + +This example shows how you can pass configuration data to the callable which +constructs the instance, in the form of keyword parameters. When run, the above +script will print:: + + changed: hello + +which shows that the filter is working as configured. + +A couple of extra points to note: + +* If you can't refer to the callable directly in the configuration (e.g. if it + lives in a different module, and you can't import it directly where the + configuration dictionary is), you can use the form ``ext://...`` as described + in :ref:`logging-config-dict-externalobj`. For example, you could have used + the text ``'ext://__main__.MyFilter'`` instead of ``MyFilter`` in the above + example. + +* As well as for filters, this technique can also be used to configure custom + handlers and formatters. See :ref:`logging-config-dict-userdef` for more + information on how logging supports using user-defined objects in its + configuration, and see the other cookbook recipe :ref:`custom-handlers` above. + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 12:52:40 2014 From: python-checkins at python.org (vinay.sajip) Date: Mon, 3 Feb 2014 12:52:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Added_cookbook?= =?utf-8?q?_entry_on_logging_filter_configuration_using_dictConfig=28=29?= =?utf-8?q?=2E?= Message-ID: <3fHnTh6nGpz7LjP@mail.python.org> http://hg.python.org/cpython/rev/58726e13dea1 changeset: 88922:58726e13dea1 branch: 3.3 parent: 88913:99168e7d4a3d user: Vinay Sajip date: Mon Feb 03 11:51:45 2014 +0000 summary: Added cookbook entry on logging filter configuration using dictConfig(). files: Doc/howto/logging-cookbook.rst | 87 ++++++++++++++++++++++ 1 files changed, 87 insertions(+), 0 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1694,6 +1694,9 @@ Note that the order of items might be different according to the version of Python used. + +.. _custom-handlers: + .. currentmodule:: logging.config Customizing handlers with :func:`dictConfig` @@ -1948,3 +1951,87 @@ parentheses go around the format string and the arguments, not just the format string. That?s because the __ notation is just syntax sugar for a constructor call to one of the ``XXXMessage`` classes shown above. + + +.. _filters-dictconfig: + +.. currentmodule:: logging.config + +Configuring filters with :func:`dictConfig` +------------------------------------------- + +You *can* configure filters using :func:`~logging.config.dictConfig`, though it +might not be obvious at first glance how to do it (hence this recipe). Since +:class:`~logging.Filter` is the only filter class included in the standard +library, and it is unlikely to cater to many requirements (it's only there as a +base class), you will typically need to define your own :class:`~logging.Filter` +subclass with an overridden :meth:`~logging.Filter.filter` method. To do this, +specify the ``()`` key in the configuration dictionary for the filter, +specifying a callable which will be used to create the filter (a class is the +most obvious, but you can provide any callable which returns a +:class:`~logging.Filter` instance). Here is a complete example:: + + import logging + import logging.config + import sys + + class MyFilter(logging.Filter): + def __init__(self, param=None): + self.param = param + + def filter(self, record): + if self.param is None: + allow = True + else: + allow = self.param not in record.msg + if allow: + record.msg = 'changed: ' + record.msg + return allow + + LOGGING = { + 'version': 1, + 'filters': { + 'myfilter': { + '()': MyFilter, + 'param': 'noshow', + } + }, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'filters': ['myfilter'] + } + }, + 'root': { + 'level': 'DEBUG', + 'handlers': ['console'] + }, + } + + if __name__ == '__main__': + logging.config.dictConfig(LOGGING) + logging.debug('hello') + logging.debug('hello - noshow') + +This example shows how you can pass configuration data to the callable which +constructs the instance, in the form of keyword parameters. When run, the above +script will print:: + + changed: hello + +which shows that the filter is working as configured. + +A couple of extra points to note: + +* If you can't refer to the callable directly in the configuration (e.g. if it + lives in a different module, and you can't import it directly where the + configuration dictionary is), you can use the form ``ext://...`` as described + in :ref:`logging-config-dict-externalobj`. For example, you could have used + the text ``'ext://__main__.MyFilter'`` instead of ``MyFilter`` in the above + example. + +* As well as for filters, this technique can also be used to configure custom + handlers and formatters. See :ref:`logging-config-dict-userdef` for more + information on how logging supports using user-defined objects in its + configuration, and see the other cookbook recipe :ref:`custom-handlers` above. + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 12:52:42 2014 From: python-checkins at python.org (vinay.sajip) Date: Mon, 3 Feb 2014 12:52:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merged_documentation_update_from_3=2E3=2E?= Message-ID: <3fHnTk2dQQz7LmH@mail.python.org> http://hg.python.org/cpython/rev/f5178269ccb1 changeset: 88923:f5178269ccb1 parent: 88920:c19f5e4fdbe0 parent: 88922:58726e13dea1 user: Vinay Sajip date: Mon Feb 03 11:52:24 2014 +0000 summary: Merged documentation update from 3.3. files: Doc/howto/logging-cookbook.rst | 87 ++++++++++++++++++++++ 1 files changed, 87 insertions(+), 0 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1692,6 +1692,9 @@ Note that the order of items might be different according to the version of Python used. + +.. _custom-handlers: + .. currentmodule:: logging.config Customizing handlers with :func:`dictConfig` @@ -1946,3 +1949,87 @@ parentheses go around the format string and the arguments, not just the format string. That?s because the __ notation is just syntax sugar for a constructor call to one of the ``XXXMessage`` classes shown above. + + +.. _filters-dictconfig: + +.. currentmodule:: logging.config + +Configuring filters with :func:`dictConfig` +------------------------------------------- + +You *can* configure filters using :func:`~logging.config.dictConfig`, though it +might not be obvious at first glance how to do it (hence this recipe). Since +:class:`~logging.Filter` is the only filter class included in the standard +library, and it is unlikely to cater to many requirements (it's only there as a +base class), you will typically need to define your own :class:`~logging.Filter` +subclass with an overridden :meth:`~logging.Filter.filter` method. To do this, +specify the ``()`` key in the configuration dictionary for the filter, +specifying a callable which will be used to create the filter (a class is the +most obvious, but you can provide any callable which returns a +:class:`~logging.Filter` instance). Here is a complete example:: + + import logging + import logging.config + import sys + + class MyFilter(logging.Filter): + def __init__(self, param=None): + self.param = param + + def filter(self, record): + if self.param is None: + allow = True + else: + allow = self.param not in record.msg + if allow: + record.msg = 'changed: ' + record.msg + return allow + + LOGGING = { + 'version': 1, + 'filters': { + 'myfilter': { + '()': MyFilter, + 'param': 'noshow', + } + }, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'filters': ['myfilter'] + } + }, + 'root': { + 'level': 'DEBUG', + 'handlers': ['console'] + }, + } + + if __name__ == '__main__': + logging.config.dictConfig(LOGGING) + logging.debug('hello') + logging.debug('hello - noshow') + +This example shows how you can pass configuration data to the callable which +constructs the instance, in the form of keyword parameters. When run, the above +script will print:: + + changed: hello + +which shows that the filter is working as configured. + +A couple of extra points to note: + +* If you can't refer to the callable directly in the configuration (e.g. if it + lives in a different module, and you can't import it directly where the + configuration dictionary is), you can use the form ``ext://...`` as described + in :ref:`logging-config-dict-externalobj`. For example, you could have used + the text ``'ext://__main__.MyFilter'`` instead of ``MyFilter`` in the above + example. + +* As well as for filters, this technique can also be used to configure custom + handlers and formatters. See :ref:`logging-config-dict-userdef` for more + information on how logging supports using user-defined objects in its + configuration, and see the other cookbook recipe :ref:`custom-handlers` above. + -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 15:19:34 2014 From: python-checkins at python.org (andrew.kuchling) Date: Mon, 3 Feb 2014 15:19:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Use_different_?= =?utf-8?q?word?= Message-ID: <3fHrlB6cTvz7LjV@mail.python.org> http://hg.python.org/cpython/rev/3afb9d94d18f changeset: 88924:3afb9d94d18f branch: 3.3 parent: 88922:58726e13dea1 user: Andrew Kuchling date: Mon Feb 03 09:04:02 2014 -0500 summary: Use different word files: Doc/tutorial/controlflow.rst | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -370,7 +370,7 @@ return False retries = retries - 1 if retries < 0: - raise IOError('refusenik user') + raise IOError('uncooperative user') print(complaint) This function can be called in several ways: @@ -756,4 +756,3 @@ .. [#] Actually, *call by object reference* would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it (items inserted into a list). - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 15:20:33 2014 From: python-checkins at python.org (andrew.kuchling) Date: Mon, 3 Feb 2014 15:20:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E3?= Message-ID: <3fHrmK3wy2z7LjV@mail.python.org> http://hg.python.org/cpython/rev/79ed8e3e3dc6 changeset: 88925:79ed8e3e3dc6 parent: 88923:f5178269ccb1 parent: 88924:3afb9d94d18f user: Andrew Kuchling date: Mon Feb 03 09:20:22 2014 -0500 summary: Merge from 3.3 files: Doc/tutorial/controlflow.rst | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -370,7 +370,7 @@ return False retries = retries - 1 if retries < 0: - raise IOError('refusenik user') + raise IOError('uncooperative user') print(complaint) This function can be called in several ways: @@ -756,4 +756,3 @@ .. [#] Actually, *call by object reference* would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it (items inserted into a list). - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 15:35:15 2014 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 3 Feb 2014 15:35:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_code_which_does_not?= =?utf-8?q?hing_but_cause_refleaks?= Message-ID: <3fHs5H0rtsz7Lk7@mail.python.org> http://hg.python.org/cpython/rev/c45a10b93a56 changeset: 88926:c45a10b93a56 user: Benjamin Peterson date: Mon Feb 03 09:35:08 2014 -0500 summary: remove code which does nothing but cause refleaks files: Modules/_opcode.c | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/Modules/_opcode.c b/Modules/_opcode.c --- a/Modules/_opcode.c +++ b/Modules/_opcode.c @@ -55,15 +55,11 @@ int effect; int oparg_int = 0; if (HAS_ARG(opcode)) { - PyObject *i_object; if (oparg == Py_None) { PyErr_SetString(PyExc_ValueError, "stack_effect: opcode requires oparg but oparg was not specified"); return -1; } - i_object = PyNumber_Index(oparg); - if (!i_object) - return -1; oparg_int = (int)PyLong_AsLong(oparg); if ((oparg_int == -1) && PyErr_Occurred()) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 19:34:02 2014 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 3 Feb 2014 19:34:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_use_system_mer?= =?utf-8?q?curial?= Message-ID: <3fHyNp5XDVz7Ln7@mail.python.org> http://hg.python.org/cpython/rev/f086503dcf54 changeset: 88927:f086503dcf54 branch: 2.7 parent: 88921:ae7facd874ba user: Benjamin Peterson date: Mon Feb 03 13:33:56 2014 -0500 summary: use system mercurial files: Doc/tools/dailybuild.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/dailybuild.py b/Doc/tools/dailybuild.py --- a/Doc/tools/dailybuild.py +++ b/Doc/tools/dailybuild.py @@ -43,7 +43,7 @@ print 'Doc autobuild started in %s' % checkout os.chdir(checkout) print 'Running hg pull --update' - os.system('/usr/local/bin/hg pull --update') + os.system('hg pull --update') print 'Running make autobuild' maketarget = 'autobuild-' + ('html' if quick else ('dev' if isdev else 'stable')) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:08:06 2014 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 3 Feb 2014 20:08:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_extra_backtick?= Message-ID: <3fHz8654L8z7Lnl@mail.python.org> http://hg.python.org/cpython/rev/825d8e5c8b61 changeset: 88928:825d8e5c8b61 parent: 88926:c45a10b93a56 user: Benjamin Peterson date: Mon Feb 03 14:08:00 2014 -0500 summary: remove extra backtick files: Doc/library/asyncio-subprocess.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -8,7 +8,7 @@ .. function:: create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds) - Run the shell command *cmd* (:class:`str`)`. Return a :class:`Process` + Run the shell command *cmd* given as a string. Return a :class:`Process` instance. This function returns a :ref:`coroutine object `. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:32 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwMzY4?= =?utf-8?q?=3A_Add_tests_for_Tkinter_methods_exprstring=28=29=2C_exprdoubl?= =?utf-8?b?ZSgpLA==?= Message-ID: <3fHzrN0CX0z7LjV@mail.python.org> http://hg.python.org/cpython/rev/a6ba6db9edb4 changeset: 88929:a6ba6db9edb4 branch: 2.7 parent: 88921:ae7facd874ba user: Serhiy Storchaka date: Mon Feb 03 20:41:04 2014 +0200 summary: Issue #20368: Add tests for Tkinter methods exprstring(), exprdouble(), exprlong() and exprboolean(). files: Lib/test/test_tcl.py | 131 +++++++++++++++++++++++++++++++ 1 files changed, 131 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -189,6 +189,137 @@ self.assertEqual(p.wait(), 0, 'Non-zero exit code') + def test_exprstring(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprstring(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, str) + + self.assertRaises(TypeError, tcl.exprstring) + self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6') + self.assertRaises(TclError, tcl.exprstring, 'spam') + check('', '0') + check('8.2 + 6', '14.2') + check('2**64', str(2**64)) + check('3.1 + $a', '6.1') + check('2 + "$a.$b"', '5.6') + check('4*[llength "6 2"]', '8') + check('{word one} < "word $a"', '0') + check('4*2 < 7', '0') + check('hypot($a, 4)', '5.0') + check('5 / 4', '1') + check('5 / 4.0', '1.25') + check('5 / ( [string length "abcd"] + 0.0 )', '1.25') + check('20.0/5.0', '4.0') + check('"0x03" > "2"', '1') + check('[string length "a\xc2\xbd\xe2\x82\xac"]', '3') + check(r'[string length "a\xbd\u20ac"]', '3') + check('"abc"', 'abc') + check('"a\xc2\xbd\xe2\x82\xac"', 'a\xc2\xbd\xe2\x82\xac') + check(r'"a\xbd\u20ac"', 'a\xc2\xbd\xe2\x82\xac') + + def test_exprdouble(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprdouble(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, float) + + self.assertRaises(TypeError, tcl.exprdouble) + self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6') + self.assertRaises(TclError, tcl.exprdouble, 'spam') + check('', 0.0) + check('8.2 + 6', 14.2) + check('2**64', float(2**64)) + check('3.1 + $a', 6.1) + check('2 + "$a.$b"', 5.6) + check('4*[llength "6 2"]', 8.0) + check('{word one} < "word $a"', 0.0) + check('4*2 < 7', 0.0) + check('hypot($a, 4)', 5.0) + check('5 / 4', 1.0) + check('5 / 4.0', 1.25) + check('5 / ( [string length "abcd"] + 0.0 )', 1.25) + check('20.0/5.0', 4.0) + check('"0x03" > "2"', 1.0) + check('[string length "a\xc2\xbd\xe2\x82\xac"]', 3.0) + check(r'[string length "a\xbd\u20ac"]', 3.0) + self.assertRaises(TclError, tcl.exprdouble, '"abc"') + + def test_exprlong(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprlong(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + + self.assertRaises(TypeError, tcl.exprlong) + self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6') + self.assertRaises(TclError, tcl.exprlong, 'spam') + check('', 0) + check('8.2 + 6', 14) + self.assertRaises(TclError, tcl.exprlong, '2**64') + check('3.1 + $a', 6) + check('2 + "$a.$b"', 5) + check('4*[llength "6 2"]', 8) + check('{word one} < "word $a"', 0) + check('4*2 < 7', 0) + check('hypot($a, 4)', 5) + check('5 / 4', 1) + check('5 / 4.0', 1) + check('5 / ( [string length "abcd"] + 0.0 )', 1) + check('20.0/5.0', 4) + check('"0x03" > "2"', 1) + check('[string length "a\xc2\xbd\xe2\x82\xac"]', 3) + check(r'[string length "a\xbd\u20ac"]', 3) + self.assertRaises(TclError, tcl.exprlong, '"abc"') + + def test_exprboolean(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprboolean(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + self.assertNotIsInstance(result, bool) + + self.assertRaises(TypeError, tcl.exprboolean) + self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6') + self.assertRaises(TclError, tcl.exprboolean, 'spam') + check('', False) + for value in ('0', 'false', 'no', 'off'): + check(value, False) + check('"%s"' % value, False) + check('{%s}' % value, False) + for value in ('1', 'true', 'yes', 'on'): + check(value, True) + check('"%s"' % value, True) + check('{%s}' % value, True) + check('8.2 + 6', True) + check('2**64', True) + check('3.1 + $a', True) + check('2 + "$a.$b"', True) + check('4*[llength "6 2"]', True) + check('{word one} < "word $a"', False) + check('4*2 < 7', False) + check('hypot($a, 4)', True) + check('5 / 4', True) + check('5 / 4.0', True) + check('5 / ( [string length "abcd"] + 0.0 )', True) + check('20.0/5.0', True) + check('"0x03" > "2"', True) + check('[string length "a\xc2\xbd\xe2\x82\xac"]', True) + check(r'[string length "a\xbd\u20ac"]', True) + self.assertRaises(TclError, tcl.exprboolean, '"abc"') + def test_passing_values(self): def passValue(value): return self.interp.call('set', '_', value) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:33 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwMzY4?= =?utf-8?q?=3A_Add_tests_for_Tkinter_methods_exprstring=28=29=2C_exprdoubl?= =?utf-8?b?ZSgpLA==?= Message-ID: <3fHzrP44dvz7Lll@mail.python.org> http://hg.python.org/cpython/rev/825c8db8b1e2 changeset: 88930:825c8db8b1e2 branch: 3.3 parent: 88924:3afb9d94d18f user: Serhiy Storchaka date: Mon Feb 03 20:41:34 2014 +0200 summary: Issue #20368: Add tests for Tkinter methods exprstring(), exprdouble(), exprlong() and exprboolean(). files: Lib/test/test_tcl.py | 135 +++++++++++++++++++++++++++++++ 1 files changed, 135 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -177,6 +177,141 @@ # exit code must be zero self.assertEqual(f.close(), None) + def test_exprstring(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprstring(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, str) + + self.assertRaises(TypeError, tcl.exprstring) + self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6') + self.assertRaises(TypeError, tcl.exprstring, b'8.2 + 6') + self.assertRaises(TclError, tcl.exprstring, 'spam') + check('', '0') + check('8.2 + 6', '14.2') + check('2**64', str(2**64)) + check('3.1 + $a', '6.1') + check('2 + "$a.$b"', '5.6') + check('4*[llength "6 2"]', '8') + check('{word one} < "word $a"', '0') + check('4*2 < 7', '0') + check('hypot($a, 4)', '5.0') + check('5 / 4', '1') + check('5 / 4.0', '1.25') + check('5 / ( [string length "abcd"] + 0.0 )', '1.25') + check('20.0/5.0', '4.0') + check('"0x03" > "2"', '1') + check('[string length "a\xbd\u20ac"]', '3') + check(r'[string length "a\xbd\u20ac"]', '3') + check('"abc"', 'abc') + check('"a\xbd\u20ac"', 'a\xbd\u20ac') + check(r'"a\xbd\u20ac"', 'a\xbd\u20ac') + + def test_exprdouble(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprdouble(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, float) + + self.assertRaises(TypeError, tcl.exprdouble) + self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6') + self.assertRaises(TypeError, tcl.exprdouble, b'8.2 + 6') + self.assertRaises(TclError, tcl.exprdouble, 'spam') + check('', 0.0) + check('8.2 + 6', 14.2) + check('2**64', float(2**64)) + check('3.1 + $a', 6.1) + check('2 + "$a.$b"', 5.6) + check('4*[llength "6 2"]', 8.0) + check('{word one} < "word $a"', 0.0) + check('4*2 < 7', 0.0) + check('hypot($a, 4)', 5.0) + check('5 / 4', 1.0) + check('5 / 4.0', 1.25) + check('5 / ( [string length "abcd"] + 0.0 )', 1.25) + check('20.0/5.0', 4.0) + check('"0x03" > "2"', 1.0) + check('[string length "a\xbd\u20ac"]', 3.0) + check(r'[string length "a\xbd\u20ac"]', 3.0) + self.assertRaises(TclError, tcl.exprdouble, '"abc"') + + def test_exprlong(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprlong(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + + self.assertRaises(TypeError, tcl.exprlong) + self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6') + self.assertRaises(TypeError, tcl.exprlong, b'8.2 + 6') + self.assertRaises(TclError, tcl.exprlong, 'spam') + check('', 0) + check('8.2 + 6', 14) + self.assertRaises(TclError, tcl.exprlong, '2**64') + check('3.1 + $a', 6) + check('2 + "$a.$b"', 5) + check('4*[llength "6 2"]', 8) + check('{word one} < "word $a"', 0) + check('4*2 < 7', 0) + check('hypot($a, 4)', 5) + check('5 / 4', 1) + check('5 / 4.0', 1) + check('5 / ( [string length "abcd"] + 0.0 )', 1) + check('20.0/5.0', 4) + check('"0x03" > "2"', 1) + check('[string length "a\xbd\u20ac"]', 3) + check(r'[string length "a\xbd\u20ac"]', 3) + self.assertRaises(TclError, tcl.exprlong, '"abc"') + + def test_exprboolean(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprboolean(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + self.assertNotIsInstance(result, bool) + + self.assertRaises(TypeError, tcl.exprboolean) + self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6') + self.assertRaises(TypeError, tcl.exprboolean, b'8.2 + 6') + self.assertRaises(TclError, tcl.exprboolean, 'spam') + check('', False) + for value in ('0', 'false', 'no', 'off'): + check(value, False) + check('"%s"' % value, False) + check('{%s}' % value, False) + for value in ('1', 'true', 'yes', 'on'): + check(value, True) + check('"%s"' % value, True) + check('{%s}' % value, True) + check('8.2 + 6', True) + check('2**64', True) + check('3.1 + $a', True) + check('2 + "$a.$b"', True) + check('4*[llength "6 2"]', True) + check('{word one} < "word $a"', False) + check('4*2 < 7', False) + check('hypot($a, 4)', True) + check('5 / 4', True) + check('5 / 4.0', True) + check('5 / ( [string length "abcd"] + 0.0 )', True) + check('20.0/5.0', True) + check('"0x03" > "2"', True) + check('[string length "a\xbd\u20ac"]', True) + check(r'[string length "a\xbd\u20ac"]', True) + self.assertRaises(TclError, tcl.exprboolean, '"abc"') + def test_passing_values(self): def passValue(value): return self.interp.call('set', '_', value) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:34 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_Merge_heads?= Message-ID: <3fHzrQ5xJWz7LlC@mail.python.org> http://hg.python.org/cpython/rev/920f29a47d49 changeset: 88931:920f29a47d49 branch: 2.7 parent: 88929:a6ba6db9edb4 parent: 88927:f086503dcf54 user: Serhiy Storchaka date: Mon Feb 03 20:42:43 2014 +0200 summary: Merge heads files: Doc/tools/dailybuild.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/dailybuild.py b/Doc/tools/dailybuild.py --- a/Doc/tools/dailybuild.py +++ b/Doc/tools/dailybuild.py @@ -43,7 +43,7 @@ print 'Doc autobuild started in %s' % checkout os.chdir(checkout) print 'Running hg pull --update' - os.system('/usr/local/bin/hg pull --update') + os.system('hg pull --update') print 'Running make autobuild' maketarget = 'autobuild-' + ('html' if quick else ('dev' if isdev else 'stable')) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:36 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320368=3A_Add_tests_for_Tkinter_methods_exprstri?= =?utf-8?b?bmcoKSwgZXhwcmRvdWJsZSgpLA==?= Message-ID: <3fHzrS1Pfwz7LjN@mail.python.org> http://hg.python.org/cpython/rev/28ec384e7dcc changeset: 88932:28ec384e7dcc parent: 88926:c45a10b93a56 parent: 88930:825c8db8b1e2 user: Serhiy Storchaka date: Mon Feb 03 20:46:14 2014 +0200 summary: Issue #20368: Add tests for Tkinter methods exprstring(), exprdouble(), exprlong() and exprboolean(). files: Lib/test/test_tcl.py | 135 +++++++++++++++++++++++++++++++ 1 files changed, 135 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -177,6 +177,141 @@ # exit code must be zero self.assertEqual(f.close(), None) + def test_exprstring(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprstring(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, str) + + self.assertRaises(TypeError, tcl.exprstring) + self.assertRaises(TypeError, tcl.exprstring, '8.2', '+6') + self.assertRaises(TypeError, tcl.exprstring, b'8.2 + 6') + self.assertRaises(TclError, tcl.exprstring, 'spam') + check('', '0') + check('8.2 + 6', '14.2') + check('2**64', str(2**64)) + check('3.1 + $a', '6.1') + check('2 + "$a.$b"', '5.6') + check('4*[llength "6 2"]', '8') + check('{word one} < "word $a"', '0') + check('4*2 < 7', '0') + check('hypot($a, 4)', '5.0') + check('5 / 4', '1') + check('5 / 4.0', '1.25') + check('5 / ( [string length "abcd"] + 0.0 )', '1.25') + check('20.0/5.0', '4.0') + check('"0x03" > "2"', '1') + check('[string length "a\xbd\u20ac"]', '3') + check(r'[string length "a\xbd\u20ac"]', '3') + check('"abc"', 'abc') + check('"a\xbd\u20ac"', 'a\xbd\u20ac') + check(r'"a\xbd\u20ac"', 'a\xbd\u20ac') + + def test_exprdouble(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprdouble(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, float) + + self.assertRaises(TypeError, tcl.exprdouble) + self.assertRaises(TypeError, tcl.exprdouble, '8.2', '+6') + self.assertRaises(TypeError, tcl.exprdouble, b'8.2 + 6') + self.assertRaises(TclError, tcl.exprdouble, 'spam') + check('', 0.0) + check('8.2 + 6', 14.2) + check('2**64', float(2**64)) + check('3.1 + $a', 6.1) + check('2 + "$a.$b"', 5.6) + check('4*[llength "6 2"]', 8.0) + check('{word one} < "word $a"', 0.0) + check('4*2 < 7', 0.0) + check('hypot($a, 4)', 5.0) + check('5 / 4', 1.0) + check('5 / 4.0', 1.25) + check('5 / ( [string length "abcd"] + 0.0 )', 1.25) + check('20.0/5.0', 4.0) + check('"0x03" > "2"', 1.0) + check('[string length "a\xbd\u20ac"]', 3.0) + check(r'[string length "a\xbd\u20ac"]', 3.0) + self.assertRaises(TclError, tcl.exprdouble, '"abc"') + + def test_exprlong(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprlong(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + + self.assertRaises(TypeError, tcl.exprlong) + self.assertRaises(TypeError, tcl.exprlong, '8.2', '+6') + self.assertRaises(TypeError, tcl.exprlong, b'8.2 + 6') + self.assertRaises(TclError, tcl.exprlong, 'spam') + check('', 0) + check('8.2 + 6', 14) + self.assertRaises(TclError, tcl.exprlong, '2**64') + check('3.1 + $a', 6) + check('2 + "$a.$b"', 5) + check('4*[llength "6 2"]', 8) + check('{word one} < "word $a"', 0) + check('4*2 < 7', 0) + check('hypot($a, 4)', 5) + check('5 / 4', 1) + check('5 / 4.0', 1) + check('5 / ( [string length "abcd"] + 0.0 )', 1) + check('20.0/5.0', 4) + check('"0x03" > "2"', 1) + check('[string length "a\xbd\u20ac"]', 3) + check(r'[string length "a\xbd\u20ac"]', 3) + self.assertRaises(TclError, tcl.exprlong, '"abc"') + + def test_exprboolean(self): + tcl = self.interp + tcl.call('set', 'a', 3) + tcl.call('set', 'b', 6) + def check(expr, expected): + result = tcl.exprboolean(expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + self.assertNotIsInstance(result, bool) + + self.assertRaises(TypeError, tcl.exprboolean) + self.assertRaises(TypeError, tcl.exprboolean, '8.2', '+6') + self.assertRaises(TypeError, tcl.exprboolean, b'8.2 + 6') + self.assertRaises(TclError, tcl.exprboolean, 'spam') + check('', False) + for value in ('0', 'false', 'no', 'off'): + check(value, False) + check('"%s"' % value, False) + check('{%s}' % value, False) + for value in ('1', 'true', 'yes', 'on'): + check(value, True) + check('"%s"' % value, True) + check('{%s}' % value, True) + check('8.2 + 6', True) + check('2**64', True) + check('3.1 + $a', True) + check('2 + "$a.$b"', True) + check('4*[llength "6 2"]', True) + check('{word one} < "word $a"', False) + check('4*2 < 7', False) + check('hypot($a, 4)', True) + check('5 / 4', True) + check('5 / 4.0', True) + check('5 / ( [string length "abcd"] + 0.0 )', True) + check('20.0/5.0', True) + check('"0x03" > "2"', True) + check('[string length "a\xbd\u20ac"]', True) + check(r'[string length "a\xbd\u20ac"]', True) + self.assertRaises(TclError, tcl.exprboolean, '"abc"') + def test_passing_values(self): def passValue(value): return self.interp.call('set', '_', value) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:37 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwMzY4?= =?utf-8?q?=3A_The_null_character_now_correctly_passed_from_Tcl_to_Python_?= =?utf-8?b?KGlu?= Message-ID: <3fHzrT5Cbbz7Lk7@mail.python.org> http://hg.python.org/cpython/rev/65c29c07bb31 changeset: 88933:65c29c07bb31 branch: 2.7 parent: 88931:920f29a47d49 user: Serhiy Storchaka date: Mon Feb 03 21:23:46 2014 +0200 summary: Issue #20368: The null character now correctly passed from Tcl to Python (in unicode strings only). Improved error handling in variables-related commands. files: Lib/lib-tk/test/test_tkinter/test_variables.py | 14 + Lib/test/test_tcl.py | 47 +- Misc/NEWS | 3 + Modules/_tkinter.c | 217 +++++---- 4 files changed, 175 insertions(+), 106 deletions(-) diff --git a/Lib/lib-tk/test/test_tkinter/test_variables.py b/Lib/lib-tk/test/test_tkinter/test_variables.py --- a/Lib/lib-tk/test/test_tkinter/test_variables.py +++ b/Lib/lib-tk/test/test_tkinter/test_variables.py @@ -58,6 +58,14 @@ with self.assertRaises(TypeError): Variable(self.root, name=123) + def test_null_in_name(self): + with self.assertRaises(ValueError): + Variable(self.root, name='var\x00name') + with self.assertRaises(ValueError): + self.root.globalsetvar('var\x00name', "value") + with self.assertRaises(ValueError): + self.root.setvar('var\x00name', "value") + class TestStringVar(TestBase): @@ -71,6 +79,12 @@ self.root.globalsetvar("name", "value") self.assertEqual("value", v.get()) + def test_get_null(self): + v = StringVar(self.root, "abc\x00def", "name") + self.assertEqual("abc\x00def", v.get()) + self.root.globalsetvar("name", "val\x00ue") + self.assertEqual("val\x00ue", v.get()) + class TestIntVar(TestBase): diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -139,6 +139,18 @@ self.assertEqual(tcl.eval('set b'),'2') self.assertEqual(tcl.eval('set c'),'3') + def test_evalfile_null_in_result(self): + tcl = self.interp + with open(test_support.TESTFN, 'wb') as f: + self.addCleanup(test_support.unlink, test_support.TESTFN) + f.write(""" + set a "a\0b" + set b "a\\0b" + """) + tcl.evalfile(test_support.TESTFN) + self.assertEqual(tcl.eval('set a'), 'a\xc0\x80b') + self.assertEqual(tcl.eval('set b'), 'a\xc0\x80b') + def testEvalFileException(self): tcl = self.interp filename = "doesnotexists" @@ -220,6 +232,7 @@ check('"abc"', 'abc') check('"a\xc2\xbd\xe2\x82\xac"', 'a\xc2\xbd\xe2\x82\xac') check(r'"a\xbd\u20ac"', 'a\xc2\xbd\xe2\x82\xac') + check(r'"a\0b"', 'a\xc0\x80b') def test_exprdouble(self): tcl = self.interp @@ -326,8 +339,17 @@ self.assertEqual(passValue(True), True if self.wantobjects else '1') self.assertEqual(passValue(False), False if self.wantobjects else '0') + self.assertEqual(passValue('string'), 'string') + self.assertEqual(passValue('string\xbd'), 'string\xbd') + self.assertEqual(passValue('string\xe2\x82\xac'), u'string\u20ac') self.assertEqual(passValue(u'string'), u'string') + self.assertEqual(passValue(u'string\xbd'), u'string\xbd') self.assertEqual(passValue(u'string\u20ac'), u'string\u20ac') + self.assertEqual(passValue('str\x00ing'), 'str\x00ing') + self.assertEqual(passValue('str\xc0\x80ing'), 'str\x00ing') + self.assertEqual(passValue(u'str\x00ing'), u'str\x00ing') + self.assertEqual(passValue(u'str\x00ing\xbd'), u'str\x00ing\xbd') + self.assertEqual(passValue(u'str\x00ing\u20ac'), u'str\x00ing\u20ac') for i in (0, 1, -1, int(2**31-1), int(-2**31)): self.assertEqual(passValue(i), i if self.wantobjects else str(i)) for f in (0.0, 1.0, -1.0, 1//3, 1/3.0, @@ -356,14 +378,16 @@ result.append(arg) return arg self.interp.createcommand('testfunc', testfunc) - def check(value, expected, eq=self.assertEqual): + def check(value, expected, expected2=None, eq=self.assertEqual): + if expected2 is None: + expected2 = expected del result[:] r = self.interp.call('testfunc', value) self.assertEqual(len(result), 1) - self.assertIsInstance(result[0], str) - eq(result[0], expected) - self.assertIsInstance(r, str) - eq(r, expected) + self.assertIsInstance(result[0], (str, unicode)) + eq(result[0], expected2) + self.assertIsInstance(r, (str, unicode)) + eq(r, expected2) def float_eq(actual, expected): expected = float(expected) self.assertAlmostEqual(float(actual), expected, @@ -376,7 +400,15 @@ check(False, '0') check('string', 'string') check('string\xbd', 'string\xbd') - check('string\u20ac', 'string\u20ac') + check('string\xe2\x82\xac', 'string\xe2\x82\xac', u'string\u20ac') + check(u'string', u'string') + check(u'string\xbd', 'string\xc2\xbd', u'string\xbd') + check(u'string\u20ac', 'string\xe2\x82\xac', u'string\u20ac') + check('str\xc0\x80ing', 'str\xc0\x80ing', u'str\x00ing') + check('str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac', u'str\x00ing\u20ac') + check(u'str\x00ing', 'str\xc0\x80ing', u'str\x00ing') + check(u'str\x00ing\xbd', 'str\xc0\x80ing\xc2\xbd', u'str\x00ing\xbd') + check(u'str\x00ing\u20ac', 'str\xc0\x80ing\xe2\x82\xac', u'str\x00ing\u20ac') for i in (0, 1, -1, 2**31-1, -2**31): check(i, str(i)) for f in (0.0, 1.0, -1.0): @@ -405,6 +437,7 @@ (u'a\n b\t\r c\n ', ('a', 'b', 'c')), ('a \xe2\x82\xac', ('a', '\xe2\x82\xac')), (u'a \u20ac', ('a', '\xe2\x82\xac')), + ('a\xc0\x80b c\xc0\x80d', ('a\xc0\x80b', 'c\xc0\x80d')), ('a {b c}', ('a', 'b c')), (r'a b\ c', ('a', 'b c')), (('a', 'b c'), ('a', 'b c')), @@ -449,6 +482,8 @@ (u'a\n b\t\r c\n ', ('a', 'b', 'c')), ('a \xe2\x82\xac', ('a', '\xe2\x82\xac')), (u'a \u20ac', ('a', '\xe2\x82\xac')), + ('a\xc0\x80b', 'a\xc0\x80b'), + ('a\xc0\x80b c\xc0\x80d', ('a\xc0\x80b', 'c\xc0\x80d')), ('a {b c}', ('a', ('b', 'c'))), (r'a b\ c', ('a', ('b', 'c'))), (('a', 'b c'), ('a', ('b', 'c'))), diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -38,6 +38,9 @@ Library ------- +- Issue #20368: The null character now correctly passed from Tcl to Python (in + unicode strings only). Improved error handling in variables-related commands. + - Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline translation settings. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -456,6 +456,68 @@ +#ifdef Py_USING_UNICODE +static PyObject * +unicode_FromTclStringAndSize(const char *s, Py_ssize_t size) +{ + PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL); + if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { + /* Tcl encodes null character as \xc0\x80 */ + if (memchr(s, '\xc0', size)) { + char *buf, *q; + const char *e = s + size; + PyErr_Clear(); + q = buf = (char *)PyMem_Malloc(size); + if (buf == NULL) + return NULL; + while (s != e) { + if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') { + *q++ = '\0'; + s += 2; + } + else + *q++ = *s++; + } + s = buf; + size = q - s; + r = PyUnicode_DecodeUTF8(s, size, NULL); + PyMem_Free(buf); + } + } + return r; +} +#endif + +static PyObject * +fromTclStringAndSize(const char *s, Py_ssize_t size) +{ + PyObject *r; +#ifdef Py_USING_UNICODE + Py_ssize_t i; + /* If Tcl string contains any bytes with the top bit set, + it's UTF-8 and we should decode it to Unicode */ + for (i = 0; i < size; i++) + if (s[i] & 0x80) + break; + if (i != size) { + /* It isn't an ASCII string. */ + r = unicode_FromTclStringAndSize(s, size); + if (r) + return r; + PyErr_Clear(); + } +#endif + r = PyString_FromStringAndSize(s, size); + return r; +} + +static PyObject * +fromTclString(const char *s) +{ + return fromTclStringAndSize(s, strlen(s)); +} + + static PyObject * Split(char *list) { @@ -841,27 +903,10 @@ static PyObject * PyTclObject_string(PyTclObject *self, void *ignored) { - char *s; - int i, len; if (!self->string) { - s = Tcl_GetStringFromObj(self->value, &len); - for (i = 0; i < len; i++) - if (s[i] & 0x80) - break; -#ifdef Py_USING_UNICODE - if (i == len) - /* It is an ASCII string. */ - self->string = PyString_FromStringAndSize(s, len); - else { - self->string = PyUnicode_DecodeUTF8(s, len, "strict"); - if (!self->string) { - PyErr_Clear(); - self->string = PyString_FromStringAndSize(s, len); - } - } -#else - self->string = PyString_FromStringAndSize(s, len); -#endif + int len; + char *s = Tcl_GetStringFromObj(self->value, &len); + self->string = fromTclStringAndSize(s, len); if (!self->string) return NULL; } @@ -883,7 +928,7 @@ } /* XXX Could chache result if it is non-ASCII. */ s = Tcl_GetStringFromObj(self->value, &len); - return PyUnicode_DecodeUTF8(s, len, "strict"); + return unicode_FromTclStringAndSize(s, len); } #endif @@ -1022,6 +1067,8 @@ PyErr_SetString(PyExc_OverflowError, "string is too long"); return NULL; } + if (sizeof(Py_UNICODE) == sizeof(Tcl_UniChar)) + return Tcl_NewUnicodeObj(inbuf, size); allocsize = ((size_t)size) * sizeof(Tcl_UniChar); if (allocsize >= size) outbuf = (Tcl_UniChar*)ckalloc(allocsize); @@ -1073,30 +1120,7 @@ TkappObject *app = (TkappObject*)tkapp; if (value->typePtr == NULL) { - /* If the result contains any bytes with the top bit set, - it's UTF-8 and we should decode it to Unicode */ -#ifdef Py_USING_UNICODE - int i; - char *s = value->bytes; - int len = value->length; - for (i = 0; i < len; i++) { - if (value->bytes[i] & 0x80) - break; - } - - if (i == value->length) - result = PyString_FromStringAndSize(s, len); - else { - /* Convert UTF-8 to Unicode string */ - result = PyUnicode_DecodeUTF8(s, len, "strict"); - if (result == NULL) { - PyErr_Clear(); - result = PyString_FromStringAndSize(s, len); - } - } -#else - result = PyString_FromStringAndSize(value->bytes, value->length); -#endif + result = fromTclStringAndSize(value->bytes, value->length); return result; } @@ -1273,8 +1297,8 @@ Tkapp_CallResult(TkappObject *self) { PyObject *res = NULL; + Tcl_Obj *value = Tcl_GetObjResult(self->interp); if(self->wantobjects) { - Tcl_Obj *value = Tcl_GetObjResult(self->interp); /* Not sure whether the IncrRef is necessary, but something may overwrite the interpreter result while we are converting it. */ @@ -1282,33 +1306,9 @@ res = FromObj((PyObject*)self, value); Tcl_DecrRefCount(value); } else { - const char *s = Tcl_GetStringResult(self->interp); - const char *p = s; - - /* If the result contains any bytes with the top bit set, - it's UTF-8 and we should decode it to Unicode */ -#ifdef Py_USING_UNICODE - while (*p != '\0') { - if (*p & 0x80) - break; - p++; - } - - if (*p == '\0') - res = PyString_FromStringAndSize(s, (int)(p-s)); - else { - /* Convert UTF-8 to Unicode string */ - p = strchr(p, '\0'); - res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict"); - if (res == NULL) { - PyErr_Clear(); - res = PyString_FromStringAndSize(s, (int)(p-s)); - } - } -#else - p = strchr(p, '\0'); - res = PyString_FromStringAndSize(s, (int)(p-s)); -#endif + int len; + const char *s = Tcl_GetStringFromObj(value, &len); + res = fromTclStringAndSize(s, len); } return res; } @@ -1611,16 +1611,28 @@ static int varname_converter(PyObject *in, void *_out) { + char *s; char **out = (char**)_out; if (PyString_Check(in)) { - *out = PyString_AsString(in); + if (PyString_Size(in) > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "string is too long"); + return 0; + } + s = PyString_AsString(in); + if (strlen(s) != PyString_Size(in)) { + PyErr_SetString(PyExc_ValueError, "null character in string"); + return 0; + } + *out = s; return 1; } if (PyTclObject_Check(in)) { *out = PyTclObject_TclString(in); return 1; } - /* XXX: Should give diagnostics. */ + PyErr_Format(PyExc_TypeError, + "must be str or Tcl_Obj, not %.50s", + in->ob_type->tp_name); return 0; } @@ -1706,8 +1718,11 @@ PyObject *res = NULL; Tcl_Obj *newval, *ok; - if (PyArg_ParseTuple(args, "O&O:setvar", - varname_converter, &name1, &newValue)) { + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "O&O:setvar", + varname_converter, &name1, &newValue)) + return NULL; /* XXX Acquire tcl lock??? */ newval = AsObj(newValue); if (newval == NULL) @@ -1723,27 +1738,27 @@ Py_INCREF(res); } LEAVE_OVERLAP_TCL - } - else { - PyErr_Clear(); - if (PyArg_ParseTuple(args, "ssO:setvar", - &name1, &name2, &newValue)) { - /* XXX must hold tcl lock already??? */ - newval = AsObj(newValue); - ENTER_TCL - ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags); - ENTER_OVERLAP - if (!ok) - Tkinter_Error(self); - else { - res = Py_None; - Py_INCREF(res); - } - LEAVE_OVERLAP_TCL + break; + case 3: + if (!PyArg_ParseTuple(args, "ssO:setvar", + &name1, &name2, &newValue)) + return NULL; + /* XXX must hold tcl lock already??? */ + newval = AsObj(newValue); + ENTER_TCL + ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags); + ENTER_OVERLAP + if (!ok) + Tkinter_Error(self); + else { + res = Py_None; + Py_INCREF(res); } - else { - return NULL; - } + LEAVE_OVERLAP_TCL + break; + default: + PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments"); + return NULL; } return res; } @@ -1783,7 +1798,9 @@ res = FromObj(self, tres); } else { - res = PyString_FromString(Tcl_GetString(tres)); + int len; + char *s = Tcl_GetStringFromObj(tres, &len); + res = PyString_FromStringAndSize(s, len); } } LEAVE_OVERLAP_TCL @@ -1921,7 +1938,7 @@ if (retval == TCL_ERROR) res = Tkinter_Error(self); else - res = Py_BuildValue("s", Tkapp_Result(self)); + res = PyString_FromString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } @@ -2158,7 +2175,7 @@ return PythonCmd_Error(interp); for (i = 0; i < (argc - 1); i++) { - PyObject *s = PyString_FromString(argv[i + 1]); + PyObject *s = fromTclString(argv[i + 1]); if (!s || PyTuple_SetItem(arg, i, s)) { Py_DECREF(arg); return PythonCmd_Error(interp); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:39 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwMzY4?= =?utf-8?q?=3A_The_null_character_now_correctly_passed_from_Tcl_to_Python?= =?utf-8?q?=2E?= Message-ID: <3fHzrW32qnz7Lmy@mail.python.org> http://hg.python.org/cpython/rev/08e3343f01a5 changeset: 88934:08e3343f01a5 branch: 3.3 parent: 88930:825c8db8b1e2 user: Serhiy Storchaka date: Mon Feb 03 21:24:07 2014 +0200 summary: Issue #20368: The null character now correctly passed from Tcl to Python. Improved error handling in variables-related commands. files: Lib/test/test_tcl.py | 50 ++- Lib/tkinter/test/test_tkinter/test_variables.py | 18 + Misc/NEWS | 3 + Modules/_tkinter.c | 184 ++++++--- 4 files changed, 176 insertions(+), 79 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -55,6 +55,10 @@ tcl.eval('set a 1') self.assertEqual(tcl.eval('set a'),'1') + def test_eval_null_in_result(self): + tcl = self.interp + self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b') + def testEvalException(self): tcl = self.interp self.assertRaises(TclError,tcl.eval,'set a') @@ -127,20 +131,29 @@ def testEvalFile(self): tcl = self.interp - filename = "testEvalFile.tcl" - fd = open(filename,'w') - script = """set a 1 - set b 2 - set c [ expr $a + $b ] - """ - fd.write(script) - fd.close() - tcl.evalfile(filename) - os.remove(filename) + with open(support.TESTFN, 'w') as f: + self.addCleanup(support.unlink, support.TESTFN) + f.write("""set a 1 + set b 2 + set c [ expr $a + $b ] + """) + tcl.evalfile(support.TESTFN) self.assertEqual(tcl.eval('set a'),'1') self.assertEqual(tcl.eval('set b'),'2') self.assertEqual(tcl.eval('set c'),'3') + def test_evalfile_null_in_result(self): + tcl = self.interp + with open(support.TESTFN, 'w') as f: + self.addCleanup(support.unlink, support.TESTFN) + f.write(""" + set a "a\0b" + set b "a\\0b" + """) + tcl.evalfile(support.TESTFN) + self.assertEqual(tcl.eval('set a'), 'a\x00b') + self.assertEqual(tcl.eval('set b'), 'a\x00b') + def testEvalFileException(self): tcl = self.interp filename = "doesnotexists" @@ -209,6 +222,7 @@ check('"abc"', 'abc') check('"a\xbd\u20ac"', 'a\xbd\u20ac') check(r'"a\xbd\u20ac"', 'a\xbd\u20ac') + check(r'"a\0b"', 'a\x00b') def test_exprdouble(self): tcl = self.interp @@ -320,6 +334,11 @@ self.assertEqual(passValue(False), False if self.wantobjects else '0') self.assertEqual(passValue('string'), 'string') self.assertEqual(passValue('string\u20ac'), 'string\u20ac') + self.assertEqual(passValue('str\x00ing'), 'str\x00ing') + self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd') + self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac') + self.assertEqual(passValue(b'str\x00ing'), 'str\x00ing') + self.assertEqual(passValue(b'str\xc0\x80ing'), 'str\x00ing') for i in (0, 1, -1, 2**31-1, -2**31): self.assertEqual(passValue(i), i if self.wantobjects else str(i)) for f in (0.0, 1.0, -1.0, 1/3, @@ -368,6 +387,13 @@ check('string', 'string') check('string\xbd', 'string\xbd') check('string\u20ac', 'string\u20ac') + check(b'string', 'string') + check(b'string\xe2\x82\xac', 'string\u20ac') + check('str\x00ing', 'str\x00ing') + check('str\x00ing\xbd', 'str\x00ing\xbd') + check('str\x00ing\u20ac', 'str\x00ing\u20ac') + check(b'str\xc0\x80ing', 'str\x00ing') + check(b'str\xc0\x80ing\xe2\x82\xac', 'str\x00ing\u20ac') for i in (0, 1, -1, 2**31-1, -2**31): check(i, str(i)) for f in (0.0, 1.0, -1.0): @@ -396,6 +422,7 @@ (b'a\n b\t\r c\n ', ('a', 'b', 'c')), ('a \u20ac', ('a', '\u20ac')), (b'a \xe2\x82\xac', ('a', '\u20ac')), + (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')), ('a {b c}', ('a', 'b c')), (r'a b\ c', ('a', 'b c')), (('a', 'b c'), ('a', 'b c')), @@ -438,6 +465,9 @@ (b'a\n b\t\r c\n ', ('a', 'b', 'c')), ('a \u20ac', ('a', '\u20ac')), (b'a \xe2\x82\xac', ('a', '\u20ac')), + (b'a\xc0\x80b', 'a\x00b'), + (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')), + (b'{a\xc0\x80b c\xc0\x80d', '{a\x00b c\x00d'), ('a {b c}', ('a', ('b', 'c'))), (r'a b\ c', ('a', ('b', 'c'))), (('a', b'b c'), ('a', ('b', 'c'))), diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py --- a/Lib/tkinter/test/test_tkinter/test_variables.py +++ b/Lib/tkinter/test/test_tkinter/test_variables.py @@ -68,6 +68,18 @@ with self.assertRaises(TypeError): Variable(self.root, name=123) + def test_null_in_name(self): + with self.assertRaises(ValueError): + Variable(self.root, name='var\x00name') + with self.assertRaises(ValueError): + self.root.globalsetvar('var\x00name', "value") + with self.assertRaises(ValueError): + self.root.globalsetvar(b'var\x00name', "value") + with self.assertRaises(ValueError): + self.root.setvar('var\x00name', "value") + with self.assertRaises(ValueError): + self.root.setvar(b'var\x00name', "value") + def test_initialize(self): v = Var() self.assertFalse(v.side_effect) @@ -87,6 +99,12 @@ self.root.globalsetvar("name", "value") self.assertEqual("value", v.get()) + def test_get_null(self): + v = StringVar(self.root, "abc\x00def", "name") + self.assertEqual("abc\x00def", v.get()) + self.root.globalsetvar("name", "val\x00ue") + self.assertEqual("val\x00ue", v.get()) + class TestIntVar(TestBase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,9 @@ Library ------- +- Issue #20368: The null character now correctly passed from Tcl to Python. + Improved error handling in variables-related commands. + - Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline translation settings. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -419,6 +419,51 @@ static PyObject * +unicodeFromTclStringAndSize(const char *s, Py_ssize_t size) +{ + PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL); + if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { + /* Tcl encodes null character as \xc0\x80 */ + if (memchr(s, '\xc0', size)) { + char *buf, *q; + const char *e = s + size; + PyErr_Clear(); + q = buf = (char *)PyMem_Malloc(size); + if (buf == NULL) + return NULL; + while (s != e) { + if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') { + *q++ = '\0'; + s += 2; + } + else + *q++ = *s++; + } + s = buf; + size = q - s; + r = PyUnicode_DecodeUTF8(s, size, NULL); + PyMem_Free(buf); + } + } + return r; +} + +static PyObject * +unicodeFromTclString(const char *s) +{ + return unicodeFromTclStringAndSize(s, strlen(s)); +} + +static PyObject * +unicodeFromTclObj(Tcl_Obj *value) +{ + int len; + char *s = Tcl_GetStringFromObj(value, &len); + return unicodeFromTclStringAndSize(s, len); +} + + +static PyObject * Split(char *list) { int argc; @@ -435,13 +480,13 @@ * Could be a quoted string containing funnies, e.g. {"}. * Return the string itself. */ - return PyUnicode_FromString(list); + return unicodeFromTclString(list); } if (argc == 0) v = PyUnicode_FromString(""); else if (argc == 1) - v = PyUnicode_FromString(argv[0]); + v = unicodeFromTclString(argv[0]); else if ((v = PyTuple_New(argc)) != NULL) { int i; PyObject *w; @@ -780,11 +825,8 @@ static PyObject * PyTclObject_string(PyTclObject *self, void *ignored) { - char *s; - int len; if (!self->string) { - s = Tcl_GetStringFromObj(self->value, &len); - self->string = PyUnicode_FromStringAndSize(s, len); + self->string = unicodeFromTclObj(self->value); if (!self->string) return NULL; } @@ -795,15 +837,12 @@ static PyObject * PyTclObject_str(PyTclObject *self, void *ignored) { - char *s; - int len; - if (self->string && PyUnicode_Check(self->string)) { + if (self->string) { Py_INCREF(self->string); return self->string; } /* XXX Could chache result if it is non-ASCII. */ - s = Tcl_GetStringFromObj(self->value, &len); - return PyUnicode_DecodeUTF8(s, len, "strict"); + return unicodeFromTclObj(self->value); } static PyObject * @@ -873,7 +912,7 @@ static PyObject* get_typename(PyTclObject* obj, void* ignored) { - return PyUnicode_FromString(obj->value->typePtr->name); + return unicodeFromTclString(obj->value->typePtr->name); } @@ -985,6 +1024,8 @@ return NULL; } kind = PyUnicode_KIND(value); + if (kind == sizeof(Tcl_UniChar)) + return Tcl_NewUnicodeObj(inbuf, size); allocsize = ((size_t)size) * sizeof(Tcl_UniChar); outbuf = (Tcl_UniChar*)ckalloc(allocsize); /* Else overflow occurred, and we take the next exit */ @@ -1035,8 +1076,7 @@ TkappObject *app = (TkappObject*)tkapp; if (value->typePtr == NULL) { - return PyUnicode_FromStringAndSize(value->bytes, - value->length); + return unicodeFromTclStringAndSize(value->bytes, value->length); } if (value->typePtr == app->BooleanType) { @@ -1093,15 +1133,9 @@ } if (value->typePtr == app->StringType) { -#if TCL_UTF_MAX==3 return PyUnicode_FromKindAndData( - PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value), + sizeof(Tcl_UniChar), Tcl_GetUnicode(value), Tcl_GetCharLength(value)); -#else - return PyUnicode_FromKindAndData( - PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value), - Tcl_GetCharLength(value)); -#endif } return newPyTclObject(value); @@ -1195,8 +1229,8 @@ Tkapp_CallResult(TkappObject *self) { PyObject *res = NULL; + Tcl_Obj *value = Tcl_GetObjResult(self->interp); if(self->wantobjects) { - Tcl_Obj *value = Tcl_GetObjResult(self->interp); /* Not sure whether the IncrRef is necessary, but something may overwrite the interpreter result while we are converting it. */ @@ -1204,7 +1238,7 @@ res = FromObj((PyObject*)self, value); Tcl_DecrRefCount(value); } else { - res = PyUnicode_FromString(Tcl_GetStringResult(self->interp)); + res = unicodeFromTclObj(value); } return res; } @@ -1395,7 +1429,7 @@ if (err == TCL_ERROR) res = Tkinter_Error(self); else - res = PyUnicode_FromString(Tkapp_Result(self)); + res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } @@ -1445,9 +1479,8 @@ ENTER_OVERLAP if (err == TCL_ERROR) res = Tkinter_Error(self); - else - res = PyUnicode_FromString(Tkapp_Result(self)); + res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } @@ -1470,7 +1503,7 @@ if (err == TCL_ERROR) res = Tkinter_Error(self); else - res = PyUnicode_FromString(Tkapp_Result(self)); + res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } @@ -1517,20 +1550,42 @@ static int varname_converter(PyObject *in, void *_out) { + char *s; char **out = (char**)_out; if (PyBytes_Check(in)) { - *out = PyBytes_AsString(in); + if (PyBytes_Size(in) > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "bytes object is too long"); + return 0; + } + s = PyBytes_AsString(in); + if (strlen(s) != PyBytes_Size(in)) { + PyErr_SetString(PyExc_ValueError, "null byte in bytes object"); + return 0; + } + *out = s; return 1; } if (PyUnicode_Check(in)) { - *out = _PyUnicode_AsString(in); + Py_ssize_t size; + s = PyUnicode_AsUTF8AndSize(in, &size); + if (size > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "string is too long"); + return 0; + } + if (strlen(s) != size) { + PyErr_SetString(PyExc_ValueError, "null character in string"); + return 0; + } + *out = s; return 1; } if (PyTclObject_Check(in)) { *out = PyTclObject_TclString(in); return 1; } - /* XXX: Should give diagnostics. */ + PyErr_Format(PyExc_TypeError, + "must be str, bytes or Tcl_Obj, not %.50s", + in->ob_type->tp_name); return 0; } @@ -1616,8 +1671,11 @@ PyObject *res = NULL; Tcl_Obj *newval, *ok; - if (PyArg_ParseTuple(args, "O&O:setvar", - varname_converter, &name1, &newValue)) { + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "O&O:setvar", + varname_converter, &name1, &newValue)) + return NULL; /* XXX Acquire tcl lock??? */ newval = AsObj(newValue); if (newval == NULL) @@ -1633,27 +1691,27 @@ Py_INCREF(res); } LEAVE_OVERLAP_TCL - } - else { - PyErr_Clear(); - if (PyArg_ParseTuple(args, "ssO:setvar", - &name1, &name2, &newValue)) { - /* XXX must hold tcl lock already??? */ - newval = AsObj(newValue); - ENTER_TCL - ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags); - ENTER_OVERLAP - if (!ok) - Tkinter_Error(self); - else { - res = Py_None; - Py_INCREF(res); - } - LEAVE_OVERLAP_TCL + break; + case 3: + if (!PyArg_ParseTuple(args, "ssO:setvar", + &name1, &name2, &newValue)) + return NULL; + /* XXX must hold tcl lock already??? */ + newval = AsObj(newValue); + ENTER_TCL + ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags); + ENTER_OVERLAP + if (!ok) + Tkinter_Error(self); + else { + res = Py_None; + Py_INCREF(res); } - else { - return NULL; - } + LEAVE_OVERLAP_TCL + break; + default: + PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments"); + return NULL; } return res; } @@ -1693,7 +1751,7 @@ res = FromObj(self, tres); } else { - res = PyUnicode_FromString(Tcl_GetString(tres)); + res = unicodeFromTclObj(tres); } } LEAVE_OVERLAP_TCL @@ -1831,7 +1889,7 @@ if (retval == TCL_ERROR) res = Tkinter_Error(self); else - res = Py_BuildValue("s", Tkapp_Result(self)); + res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } @@ -1956,7 +2014,7 @@ goto finally; for (i = 0; i < argc; i++) { - PyObject *s = PyUnicode_FromString(argv[i]); + PyObject *s = unicodeFromTclString(argv[i]); if (!s || PyTuple_SetItem(v, i, s)) { Py_DECREF(v); v = NULL; @@ -2075,20 +2133,8 @@ return PythonCmd_Error(interp); for (i = 0; i < (argc - 1); i++) { - PyObject *s = PyUnicode_FromString(argv[i + 1]); - if (!s) { - /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */ - if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) && - !strcmp(argv[i + 1], "\xC0\x80")) { - PyErr_Clear(); - /* Convert to "strict" utf-8 null */ - s = PyUnicode_FromString("\0"); - } else { - Py_DECREF(arg); - return PythonCmd_Error(interp); - } - } - if (PyTuple_SetItem(arg, i, s)) { + PyObject *s = unicodeFromTclString(argv[i + 1]); + if (!s || PyTuple_SetItem(arg, i, s)) { Py_DECREF(arg); return PythonCmd_Error(interp); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:41 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:41 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320368=3A_The_null_character_now_correctly_passe?= =?utf-8?q?d_from_Tcl_to_Python=2E?= Message-ID: <3fHzrY0CWVz7LmD@mail.python.org> http://hg.python.org/cpython/rev/321b714653e3 changeset: 88935:321b714653e3 parent: 88932:28ec384e7dcc parent: 88934:08e3343f01a5 user: Serhiy Storchaka date: Mon Feb 03 21:25:56 2014 +0200 summary: Issue #20368: The null character now correctly passed from Tcl to Python. Improved error handling in variables-related commands. files: Lib/test/test_tcl.py | 50 ++- Lib/tkinter/test/test_tkinter/test_variables.py | 18 + Misc/NEWS | 3 + Modules/_tkinter.c | 184 ++++++--- 4 files changed, 176 insertions(+), 79 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -55,6 +55,10 @@ tcl.eval('set a 1') self.assertEqual(tcl.eval('set a'),'1') + def test_eval_null_in_result(self): + tcl = self.interp + self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b') + def testEvalException(self): tcl = self.interp self.assertRaises(TclError,tcl.eval,'set a') @@ -127,20 +131,29 @@ def testEvalFile(self): tcl = self.interp - filename = "testEvalFile.tcl" - fd = open(filename,'w') - script = """set a 1 - set b 2 - set c [ expr $a + $b ] - """ - fd.write(script) - fd.close() - tcl.evalfile(filename) - os.remove(filename) + with open(support.TESTFN, 'w') as f: + self.addCleanup(support.unlink, support.TESTFN) + f.write("""set a 1 + set b 2 + set c [ expr $a + $b ] + """) + tcl.evalfile(support.TESTFN) self.assertEqual(tcl.eval('set a'),'1') self.assertEqual(tcl.eval('set b'),'2') self.assertEqual(tcl.eval('set c'),'3') + def test_evalfile_null_in_result(self): + tcl = self.interp + with open(support.TESTFN, 'w') as f: + self.addCleanup(support.unlink, support.TESTFN) + f.write(""" + set a "a\0b" + set b "a\\0b" + """) + tcl.evalfile(support.TESTFN) + self.assertEqual(tcl.eval('set a'), 'a\x00b') + self.assertEqual(tcl.eval('set b'), 'a\x00b') + def testEvalFileException(self): tcl = self.interp filename = "doesnotexists" @@ -209,6 +222,7 @@ check('"abc"', 'abc') check('"a\xbd\u20ac"', 'a\xbd\u20ac') check(r'"a\xbd\u20ac"', 'a\xbd\u20ac') + check(r'"a\0b"', 'a\x00b') def test_exprdouble(self): tcl = self.interp @@ -320,6 +334,11 @@ self.assertEqual(passValue(False), False if self.wantobjects else '0') self.assertEqual(passValue('string'), 'string') self.assertEqual(passValue('string\u20ac'), 'string\u20ac') + self.assertEqual(passValue('str\x00ing'), 'str\x00ing') + self.assertEqual(passValue('str\x00ing\xbd'), 'str\x00ing\xbd') + self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac') + self.assertEqual(passValue(b'str\x00ing'), 'str\x00ing') + self.assertEqual(passValue(b'str\xc0\x80ing'), 'str\x00ing') for i in (0, 1, -1, 2**31-1, -2**31): self.assertEqual(passValue(i), i if self.wantobjects else str(i)) for f in (0.0, 1.0, -1.0, 1/3, @@ -368,6 +387,13 @@ check('string', 'string') check('string\xbd', 'string\xbd') check('string\u20ac', 'string\u20ac') + check(b'string', 'string') + check(b'string\xe2\x82\xac', 'string\u20ac') + check('str\x00ing', 'str\x00ing') + check('str\x00ing\xbd', 'str\x00ing\xbd') + check('str\x00ing\u20ac', 'str\x00ing\u20ac') + check(b'str\xc0\x80ing', 'str\x00ing') + check(b'str\xc0\x80ing\xe2\x82\xac', 'str\x00ing\u20ac') for i in (0, 1, -1, 2**31-1, -2**31): check(i, str(i)) for f in (0.0, 1.0, -1.0): @@ -396,6 +422,7 @@ (b'a\n b\t\r c\n ', ('a', 'b', 'c')), ('a \u20ac', ('a', '\u20ac')), (b'a \xe2\x82\xac', ('a', '\u20ac')), + (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')), ('a {b c}', ('a', 'b c')), (r'a b\ c', ('a', 'b c')), (('a', 'b c'), ('a', 'b c')), @@ -438,6 +465,9 @@ (b'a\n b\t\r c\n ', ('a', 'b', 'c')), ('a \u20ac', ('a', '\u20ac')), (b'a \xe2\x82\xac', ('a', '\u20ac')), + (b'a\xc0\x80b', 'a\x00b'), + (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')), + (b'{a\xc0\x80b c\xc0\x80d', '{a\x00b c\x00d'), ('a {b c}', ('a', ('b', 'c'))), (r'a b\ c', ('a', ('b', 'c'))), (('a', b'b c'), ('a', ('b', 'c'))), diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py --- a/Lib/tkinter/test/test_tkinter/test_variables.py +++ b/Lib/tkinter/test/test_tkinter/test_variables.py @@ -68,6 +68,18 @@ with self.assertRaises(TypeError): Variable(self.root, name=123) + def test_null_in_name(self): + with self.assertRaises(ValueError): + Variable(self.root, name='var\x00name') + with self.assertRaises(ValueError): + self.root.globalsetvar('var\x00name', "value") + with self.assertRaises(ValueError): + self.root.globalsetvar(b'var\x00name', "value") + with self.assertRaises(ValueError): + self.root.setvar('var\x00name', "value") + with self.assertRaises(ValueError): + self.root.setvar(b'var\x00name', "value") + def test_initialize(self): v = Var() self.assertFalse(v.side_effect) @@ -87,6 +99,12 @@ self.root.globalsetvar("name", "value") self.assertEqual("value", v.get()) + def test_get_null(self): + v = StringVar(self.root, "abc\x00def", "name") + self.assertEqual("abc\x00def", v.get()) + self.root.globalsetvar("name", "val\x00ue") + self.assertEqual("val\x00ue", v.get()) + class TestIntVar(TestBase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,9 @@ Library ------- +- Issue #20368: The null character now correctly passed from Tcl to Python. + Improved error handling in variables-related commands. + - Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline translation settings. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -329,6 +329,51 @@ static PyObject * +unicodeFromTclStringAndSize(const char *s, Py_ssize_t size) +{ + PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL); + if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { + /* Tcl encodes null character as \xc0\x80 */ + if (memchr(s, '\xc0', size)) { + char *buf, *q; + const char *e = s + size; + PyErr_Clear(); + q = buf = (char *)PyMem_Malloc(size); + if (buf == NULL) + return NULL; + while (s != e) { + if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') { + *q++ = '\0'; + s += 2; + } + else + *q++ = *s++; + } + s = buf; + size = q - s; + r = PyUnicode_DecodeUTF8(s, size, NULL); + PyMem_Free(buf); + } + } + return r; +} + +static PyObject * +unicodeFromTclString(const char *s) +{ + return unicodeFromTclStringAndSize(s, strlen(s)); +} + +static PyObject * +unicodeFromTclObj(Tcl_Obj *value) +{ + int len; + char *s = Tcl_GetStringFromObj(value, &len); + return unicodeFromTclStringAndSize(s, len); +} + + +static PyObject * Split(char *list) { int argc; @@ -344,13 +389,13 @@ * Could be a quoted string containing funnies, e.g. {"}. * Return the string itself. */ - return PyUnicode_FromString(list); + return unicodeFromTclString(list); } if (argc == 0) v = PyUnicode_FromString(""); else if (argc == 1) - v = PyUnicode_FromString(argv[0]); + v = unicodeFromTclString(argv[0]); else if ((v = PyTuple_New(argc)) != NULL) { int i; PyObject *w; @@ -694,11 +739,8 @@ static PyObject * PyTclObject_string(PyTclObject *self, void *ignored) { - char *s; - int len; if (!self->string) { - s = Tcl_GetStringFromObj(self->value, &len); - self->string = PyUnicode_FromStringAndSize(s, len); + self->string = unicodeFromTclObj(self->value); if (!self->string) return NULL; } @@ -709,15 +751,12 @@ static PyObject * PyTclObject_str(PyTclObject *self, void *ignored) { - char *s; - int len; - if (self->string && PyUnicode_Check(self->string)) { + if (self->string) { Py_INCREF(self->string); return self->string; } /* XXX Could chache result if it is non-ASCII. */ - s = Tcl_GetStringFromObj(self->value, &len); - return PyUnicode_DecodeUTF8(s, len, "strict"); + return unicodeFromTclObj(self->value); } static PyObject * @@ -792,7 +831,7 @@ static PyObject* get_typename(PyTclObject* obj, void* ignored) { - return PyUnicode_FromString(obj->value->typePtr->name); + return unicodeFromTclString(obj->value->typePtr->name); } @@ -879,6 +918,8 @@ return NULL; } kind = PyUnicode_KIND(value); + if (kind == sizeof(Tcl_UniChar)) + return Tcl_NewUnicodeObj(inbuf, size); allocsize = ((size_t)size) * sizeof(Tcl_UniChar); outbuf = (Tcl_UniChar*)ckalloc(allocsize); /* Else overflow occurred, and we take the next exit */ @@ -929,8 +970,7 @@ TkappObject *app = (TkappObject*)tkapp; if (value->typePtr == NULL) { - return PyUnicode_FromStringAndSize(value->bytes, - value->length); + return unicodeFromTclStringAndSize(value->bytes, value->length); } if (value->typePtr == app->BooleanType) { @@ -987,15 +1027,9 @@ } if (value->typePtr == app->StringType) { -#if TCL_UTF_MAX==3 return PyUnicode_FromKindAndData( - PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value), + sizeof(Tcl_UniChar), Tcl_GetUnicode(value), Tcl_GetCharLength(value)); -#else - return PyUnicode_FromKindAndData( - PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value), - Tcl_GetCharLength(value)); -#endif } return newPyTclObject(value); @@ -1089,8 +1123,8 @@ Tkapp_CallResult(TkappObject *self) { PyObject *res = NULL; + Tcl_Obj *value = Tcl_GetObjResult(self->interp); if(self->wantobjects) { - Tcl_Obj *value = Tcl_GetObjResult(self->interp); /* Not sure whether the IncrRef is necessary, but something may overwrite the interpreter result while we are converting it. */ @@ -1098,7 +1132,7 @@ res = FromObj((PyObject*)self, value); Tcl_DecrRefCount(value); } else { - res = PyUnicode_FromString(Tcl_GetStringResult(self->interp)); + res = unicodeFromTclObj(value); } return res; } @@ -1253,7 +1287,7 @@ if (err == TCL_ERROR) res = Tkinter_Error(self); else - res = PyUnicode_FromString(Tkapp_Result(self)); + res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } @@ -1275,9 +1309,8 @@ ENTER_OVERLAP if (err == TCL_ERROR) res = Tkinter_Error(self); - else - res = PyUnicode_FromString(Tkapp_Result(self)); + res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } @@ -1300,7 +1333,7 @@ if (err == TCL_ERROR) res = Tkinter_Error(self); else - res = PyUnicode_FromString(Tkapp_Result(self)); + res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } @@ -1346,20 +1379,42 @@ static int varname_converter(PyObject *in, void *_out) { + char *s; char **out = (char**)_out; if (PyBytes_Check(in)) { - *out = PyBytes_AsString(in); + if (PyBytes_Size(in) > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "bytes object is too long"); + return 0; + } + s = PyBytes_AsString(in); + if (strlen(s) != PyBytes_Size(in)) { + PyErr_SetString(PyExc_ValueError, "null byte in bytes object"); + return 0; + } + *out = s; return 1; } if (PyUnicode_Check(in)) { - *out = _PyUnicode_AsString(in); + Py_ssize_t size; + s = PyUnicode_AsUTF8AndSize(in, &size); + if (size > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "string is too long"); + return 0; + } + if (strlen(s) != size) { + PyErr_SetString(PyExc_ValueError, "null character in string"); + return 0; + } + *out = s; return 1; } if (PyTclObject_Check(in)) { *out = PyTclObject_TclString(in); return 1; } - /* XXX: Should give diagnostics. */ + PyErr_Format(PyExc_TypeError, + "must be str, bytes or Tcl_Obj, not %.50s", + in->ob_type->tp_name); return 0; } @@ -1445,8 +1500,11 @@ PyObject *res = NULL; Tcl_Obj *newval, *ok; - if (PyArg_ParseTuple(args, "O&O:setvar", - varname_converter, &name1, &newValue)) { + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "O&O:setvar", + varname_converter, &name1, &newValue)) + return NULL; /* XXX Acquire tcl lock??? */ newval = AsObj(newValue); if (newval == NULL) @@ -1462,27 +1520,27 @@ Py_INCREF(res); } LEAVE_OVERLAP_TCL - } - else { - PyErr_Clear(); - if (PyArg_ParseTuple(args, "ssO:setvar", - &name1, &name2, &newValue)) { - /* XXX must hold tcl lock already??? */ - newval = AsObj(newValue); - ENTER_TCL - ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags); - ENTER_OVERLAP - if (!ok) - Tkinter_Error(self); - else { - res = Py_None; - Py_INCREF(res); - } - LEAVE_OVERLAP_TCL + break; + case 3: + if (!PyArg_ParseTuple(args, "ssO:setvar", + &name1, &name2, &newValue)) + return NULL; + /* XXX must hold tcl lock already??? */ + newval = AsObj(newValue); + ENTER_TCL + ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags); + ENTER_OVERLAP + if (!ok) + Tkinter_Error(self); + else { + res = Py_None; + Py_INCREF(res); } - else { - return NULL; - } + LEAVE_OVERLAP_TCL + break; + default: + PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments"); + return NULL; } return res; } @@ -1523,7 +1581,7 @@ res = FromObj(self, tres); } else { - res = PyUnicode_FromString(Tcl_GetString(tres)); + res = unicodeFromTclObj(tres); } } LEAVE_OVERLAP_TCL @@ -1662,7 +1720,7 @@ if (retval == TCL_ERROR) res = Tkinter_Error(self); else - res = Py_BuildValue("s", Tkapp_Result(self)); + res = unicodeFromTclString(Tkapp_Result(self)); LEAVE_OVERLAP_TCL return res; } @@ -1787,7 +1845,7 @@ goto finally; for (i = 0; i < argc; i++) { - PyObject *s = PyUnicode_FromString(argv[i]); + PyObject *s = unicodeFromTclString(argv[i]); if (!s || PyTuple_SetItem(v, i, s)) { Py_DECREF(v); v = NULL; @@ -1885,20 +1943,8 @@ return PythonCmd_Error(interp); for (i = 0; i < (argc - 1); i++) { - PyObject *s = PyUnicode_FromString(argv[i + 1]); - if (!s) { - /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */ - if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) && - !strcmp(argv[i + 1], "\xC0\x80")) { - PyErr_Clear(); - /* Convert to "strict" utf-8 null */ - s = PyUnicode_FromString("\0"); - } else { - Py_DECREF(arg); - return PythonCmd_Error(interp); - } - } - if (PyTuple_SetItem(arg, i, s)) { + PyObject *s = unicodeFromTclString(argv[i + 1]); + if (!s || PyTuple_SetItem(arg, i, s)) { Py_DECREF(arg); return PythonCmd_Error(interp); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:42 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE5NzYx?= =?utf-8?q?=3A_Fixed_Tkinter_tests_on_OS_X=2E?= Message-ID: <3fHzrZ2104z7Lmy@mail.python.org> http://hg.python.org/cpython/rev/129eb818d9b2 changeset: 88936:129eb818d9b2 branch: 2.7 parent: 88933:65c29c07bb31 user: Serhiy Storchaka date: Mon Feb 03 21:33:21 2014 +0200 summary: Issue #19761: Fixed Tkinter tests on OS X. files: Lib/lib-tk/test/test_tkinter/test_widgets.py | 9 ++++--- Lib/lib-tk/test/widget_tests.py | 12 +++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Lib/lib-tk/test/test_tkinter/test_widgets.py b/Lib/lib-tk/test/test_tkinter/test_widgets.py --- a/Lib/lib-tk/test/test_tkinter/test_widgets.py +++ b/Lib/lib-tk/test/test_tkinter/test_widgets.py @@ -326,10 +326,11 @@ self.checkColorParam(widget, 'disabledbackground') def test_insertborderwidth(self): - widget = self.create() - self.checkPixelsParam(widget, 'insertborderwidth', 0, 1.3, -2) - self.checkParam(widget, 'insertborderwidth', 2, expected=1) - self.checkParam(widget, 'insertborderwidth', '10p', expected=1) + widget = self.create(insertwidth=100) + self.checkPixelsParam(widget, 'insertborderwidth', + 0, 1.3, 2.6, 6, -2, '10p') + # insertborderwidth is bounded above by a half of insertwidth. + self.checkParam(widget, 'insertborderwidth', 60, expected=100//2) def test_insertwidth(self): widget = self.create() diff --git a/Lib/lib-tk/test/widget_tests.py b/Lib/lib-tk/test/widget_tests.py --- a/Lib/lib-tk/test/widget_tests.py +++ b/Lib/lib-tk/test/widget_tests.py @@ -6,6 +6,7 @@ from ttk import setup_master, Scale from test_ttk.support import (tcl_version, requires_tcl, get_tk_patchlevel, pixels_conv, tcl_obj_eq) +import test.test_support noconv = noconv_meth = False @@ -253,8 +254,14 @@ widget = self.create() self.checkParam(widget, 'bitmap', 'questhead') self.checkParam(widget, 'bitmap', 'gray50') - self.checkInvalidParam(widget, 'bitmap', 'spam', - errmsg='bitmap "spam" not defined') + filename = test.test_support.findfile('python.xbm', subdir='imghdrdata') + self.checkParam(widget, 'bitmap', '@' + filename) + # Cocoa Tk widgets don't detect invalid -bitmap values + # See https://core.tcl.tk/tk/info/31cd33dbf0 + if not ('aqua' in self.root.tk.call('tk', 'windowingsystem') and + 'AppKit' in self.root.winfo_server()): + self.checkInvalidParam(widget, 'bitmap', 'spam', + errmsg='bitmap "spam" not defined') def test_borderwidth(self): widget = self.create() @@ -514,7 +521,6 @@ return decorator def setUpModule(): - import test.test_support if test.test_support.verbose: tcl = Tkinter.Tcl() print 'patchlevel =', tcl.call('info', 'patchlevel') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:43 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE5NzYx?= =?utf-8?q?=3A_Fixed_Tkinter_tests_on_OS_X=2E?= Message-ID: <3fHzrb3pBfz7Lll@mail.python.org> http://hg.python.org/cpython/rev/76cd2e59b13d changeset: 88937:76cd2e59b13d branch: 3.3 parent: 88934:08e3343f01a5 user: Serhiy Storchaka date: Mon Feb 03 21:33:33 2014 +0200 summary: Issue #19761: Fixed Tkinter tests on OS X. files: Lib/tkinter/test/test_tkinter/test_widgets.py | 9 ++++--- Lib/tkinter/test/widget_tests.py | 12 +++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Lib/tkinter/test/test_tkinter/test_widgets.py b/Lib/tkinter/test/test_tkinter/test_widgets.py --- a/Lib/tkinter/test/test_tkinter/test_widgets.py +++ b/Lib/tkinter/test/test_tkinter/test_widgets.py @@ -329,10 +329,11 @@ self.checkColorParam(widget, 'disabledbackground') def test_insertborderwidth(self): - widget = self.create() - self.checkPixelsParam(widget, 'insertborderwidth', 0, 1.3, -2) - self.checkParam(widget, 'insertborderwidth', 2, expected=1) - self.checkParam(widget, 'insertborderwidth', '10p', expected=1) + widget = self.create(insertwidth=100) + self.checkPixelsParam(widget, 'insertborderwidth', + 0, 1.3, 2.6, 6, -2, '10p') + # insertborderwidth is bounded above by a half of insertwidth. + self.checkParam(widget, 'insertborderwidth', 60, expected=100//2) def test_insertwidth(self): widget = self.create() diff --git a/Lib/tkinter/test/widget_tests.py b/Lib/tkinter/test/widget_tests.py --- a/Lib/tkinter/test/widget_tests.py +++ b/Lib/tkinter/test/widget_tests.py @@ -6,6 +6,7 @@ from tkinter.ttk import setup_master, Scale from tkinter.test.support import (tcl_version, requires_tcl, get_tk_patchlevel, pixels_conv, tcl_obj_eq) +import test.support noconv = False @@ -234,8 +235,14 @@ widget = self.create() self.checkParam(widget, 'bitmap', 'questhead') self.checkParam(widget, 'bitmap', 'gray50') - self.checkInvalidParam(widget, 'bitmap', 'spam', - errmsg='bitmap "spam" not defined') + filename = test.support.findfile('python.xbm', subdir='imghdrdata') + self.checkParam(widget, 'bitmap', '@' + filename) + # Cocoa Tk widgets don't detect invalid -bitmap values + # See https://core.tcl.tk/tk/info/31cd33dbf0 + if not ('aqua' in self.root.tk.call('tk', 'windowingsystem') and + 'AppKit' in self.root.winfo_server()): + self.checkInvalidParam(widget, 'bitmap', 'spam', + errmsg='bitmap "spam" not defined') def test_borderwidth(self): widget = self.create() @@ -495,7 +502,6 @@ return decorator def setUpModule(): - import test.support if test.support.verbose: tcl = tkinter.Tcl() print('patchlevel =', tcl.call('info', 'patchlevel')) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:44 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2319761=3A_Fixed_Tkinter_tests_on_OS_X=2E?= Message-ID: <3fHzrc5F5pz7LnP@mail.python.org> http://hg.python.org/cpython/rev/2efe0778a4cf changeset: 88938:2efe0778a4cf parent: 88935:321b714653e3 parent: 88937:76cd2e59b13d user: Serhiy Storchaka date: Mon Feb 03 21:34:14 2014 +0200 summary: Issue #19761: Fixed Tkinter tests on OS X. files: Lib/tkinter/test/test_tkinter/test_widgets.py | 9 ++++--- Lib/tkinter/test/widget_tests.py | 12 +++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Lib/tkinter/test/test_tkinter/test_widgets.py b/Lib/tkinter/test/test_tkinter/test_widgets.py --- a/Lib/tkinter/test/test_tkinter/test_widgets.py +++ b/Lib/tkinter/test/test_tkinter/test_widgets.py @@ -329,10 +329,11 @@ self.checkColorParam(widget, 'disabledbackground') def test_insertborderwidth(self): - widget = self.create() - self.checkPixelsParam(widget, 'insertborderwidth', 0, 1.3, -2) - self.checkParam(widget, 'insertborderwidth', 2, expected=1) - self.checkParam(widget, 'insertborderwidth', '10p', expected=1) + widget = self.create(insertwidth=100) + self.checkPixelsParam(widget, 'insertborderwidth', + 0, 1.3, 2.6, 6, -2, '10p') + # insertborderwidth is bounded above by a half of insertwidth. + self.checkParam(widget, 'insertborderwidth', 60, expected=100//2) def test_insertwidth(self): widget = self.create() diff --git a/Lib/tkinter/test/widget_tests.py b/Lib/tkinter/test/widget_tests.py --- a/Lib/tkinter/test/widget_tests.py +++ b/Lib/tkinter/test/widget_tests.py @@ -6,6 +6,7 @@ from tkinter.ttk import setup_master, Scale from tkinter.test.support import (tcl_version, requires_tcl, get_tk_patchlevel, pixels_conv, tcl_obj_eq) +import test.support noconv = False @@ -234,8 +235,14 @@ widget = self.create() self.checkParam(widget, 'bitmap', 'questhead') self.checkParam(widget, 'bitmap', 'gray50') - self.checkInvalidParam(widget, 'bitmap', 'spam', - errmsg='bitmap "spam" not defined') + filename = test.support.findfile('python.xbm', subdir='imghdrdata') + self.checkParam(widget, 'bitmap', '@' + filename) + # Cocoa Tk widgets don't detect invalid -bitmap values + # See https://core.tcl.tk/tk/info/31cd33dbf0 + if not ('aqua' in self.root.tk.call('tk', 'windowingsystem') and + 'AppKit' in self.root.winfo_server()): + self.checkInvalidParam(widget, 'bitmap', 'spam', + errmsg='bitmap "spam" not defined') def test_borderwidth(self): widget = self.create() @@ -495,7 +502,6 @@ return decorator def setUpModule(): - import test.support if test.support.verbose: tcl = tkinter.Tcl() print('patchlevel =', tcl.call('info', 'patchlevel')) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 20:39:45 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 20:39:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_heads?= Message-ID: <3fHzrd75Vjz7LjN@mail.python.org> http://hg.python.org/cpython/rev/6007e81f5867 changeset: 88939:6007e81f5867 parent: 88938:2efe0778a4cf parent: 88928:825d8e5c8b61 user: Serhiy Storchaka date: Mon Feb 03 21:36:17 2014 +0200 summary: Merge heads files: Doc/library/asyncio-subprocess.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -8,7 +8,7 @@ .. function:: create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds) - Run the shell command *cmd* (:class:`str`)`. Return a :class:`Process` + Run the shell command *cmd* given as a string. Return a :class:`Process` instance. This function returns a :ref:`coroutine object `. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 21:01:53 2014 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 3 Feb 2014 21:01:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNDI2?= =?utf-8?q?=3A_When_passing_the_re=2EDEBUG_flag=2C_re=2Ecompile=28=29_disp?= =?utf-8?q?lays_the_debug?= Message-ID: <3fJ0L915h9z7LnC@mail.python.org> http://hg.python.org/cpython/rev/a7b180d5df5f changeset: 88940:a7b180d5df5f branch: 3.3 parent: 88937:76cd2e59b13d user: Antoine Pitrou date: Mon Feb 03 20:59:59 2014 +0100 summary: Issue #20426: When passing the re.DEBUG flag, re.compile() displays the debug output every time it is called, regardless of the compilation cache. files: Lib/re.py | 17 ++++++++++------- Lib/test/test_re.py | 15 ++++++++++++++- Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Lib/re.py b/Lib/re.py --- a/Lib/re.py +++ b/Lib/re.py @@ -267,10 +267,12 @@ _MAXCACHE = 512 def _compile(pattern, flags): # internal: compile pattern - try: - return _cache[type(pattern), pattern, flags] - except KeyError: - pass + bypass_cache = flags & DEBUG + if not bypass_cache: + try: + return _cache[type(pattern), pattern, flags] + except KeyError: + pass if isinstance(pattern, _pattern_type): if flags: raise ValueError( @@ -279,9 +281,10 @@ if not sre_compile.isstring(pattern): raise TypeError("first argument must be string or compiled pattern") p = sre_compile.compile(pattern, flags) - if len(_cache) >= _MAXCACHE: - _cache.clear() - _cache[type(pattern), pattern, flags] = p + if not bypass_cache: + if len(_cache) >= _MAXCACHE: + _cache.clear() + _cache[type(pattern), pattern, flags] = p return p def _compile_repl(repl, pattern): diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1,5 +1,5 @@ from test.support import verbose, run_unittest, gc_collect, bigmemtest, _2G, \ - cpython_only + cpython_only, captured_stdout import io import re from re import Scanner @@ -1064,6 +1064,19 @@ self.assertEqual(m.group(1), "") self.assertEqual(m.group(2), "y") + def test_debug_flag(self): + with captured_stdout() as out: + re.compile('foo', re.DEBUG) + self.assertEqual(out.getvalue().splitlines(), + ['literal 102 ', 'literal 111 ', 'literal 111 ']) + # Debug output is output again even a second time (bypassing + # the cache -- issue #20426). + with captured_stdout() as out: + re.compile('foo', re.DEBUG) + self.assertEqual(out.getvalue().splitlines(), + ['literal 102 ', 'literal 111 ', 'literal 111 ']) + + def run_re_tests(): from test.re_tests import tests, SUCCEED, FAIL, SYNTAX_ERROR if verbose: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,9 @@ Library ------- +- Issue #20426: When passing the re.DEBUG flag, re.compile() displays the + debug output every time it is called, regardless of the compilation cache. + - Issue #20368: The null character now correctly passed from Tcl to Python. Improved error handling in variables-related commands. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 21:01:54 2014 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 3 Feb 2014 21:01:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320426=3A_When_passing_the_re=2EDEBUG_flag=2C_re?= =?utf-8?q?=2Ecompile=28=29_displays_the_debug?= Message-ID: <3fJ0LB2pDMz7Lnh@mail.python.org> http://hg.python.org/cpython/rev/a8bcfa290e68 changeset: 88941:a8bcfa290e68 parent: 88939:6007e81f5867 parent: 88940:a7b180d5df5f user: Antoine Pitrou date: Mon Feb 03 21:01:35 2014 +0100 summary: Issue #20426: When passing the re.DEBUG flag, re.compile() displays the debug output every time it is called, regardless of the compilation cache. files: Lib/re.py | 17 ++++++++++------- Lib/test/test_re.py | 14 +++++++++++++- Misc/NEWS | 3 +++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Lib/re.py b/Lib/re.py --- a/Lib/re.py +++ b/Lib/re.py @@ -272,10 +272,12 @@ _MAXCACHE = 512 def _compile(pattern, flags): # internal: compile pattern - try: - return _cache[type(pattern), pattern, flags] - except KeyError: - pass + bypass_cache = flags & DEBUG + if not bypass_cache: + try: + return _cache[type(pattern), pattern, flags] + except KeyError: + pass if isinstance(pattern, _pattern_type): if flags: raise ValueError( @@ -284,9 +286,10 @@ if not sre_compile.isstring(pattern): raise TypeError("first argument must be string or compiled pattern") p = sre_compile.compile(pattern, flags) - if len(_cache) >= _MAXCACHE: - _cache.clear() - _cache[type(pattern), pattern, flags] = p + if not bypass_cache: + if len(_cache) >= _MAXCACHE: + _cache.clear() + _cache[type(pattern), pattern, flags] = p return p def _compile_repl(repl, pattern): diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1,5 +1,5 @@ from test.support import verbose, run_unittest, gc_collect, bigmemtest, _2G, \ - cpython_only + cpython_only, captured_stdout import io import re from re import Scanner @@ -1193,6 +1193,18 @@ self.assertEqual(m.group(1), "") self.assertEqual(m.group(2), "y") + def test_debug_flag(self): + with captured_stdout() as out: + re.compile('foo', re.DEBUG) + self.assertEqual(out.getvalue().splitlines(), + ['literal 102 ', 'literal 111 ', 'literal 111 ']) + # Debug output is output again even a second time (bypassing + # the cache -- issue #20426). + with captured_stdout() as out: + re.compile('foo', re.DEBUG) + self.assertEqual(out.getvalue().splitlines(), + ['literal 102 ', 'literal 111 ', 'literal 111 ']) + class PatternReprTests(unittest.TestCase): def check(self, pattern, expected): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,9 @@ Library ------- +- Issue #20426: When passing the re.DEBUG flag, re.compile() displays the + debug output every time it is called, regardless of the compilation cache. + - Issue #20368: The null character now correctly passed from Tcl to Python. Improved error handling in variables-related commands. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 21:12:54 2014 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 3 Feb 2014 21:12:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNDI2?= =?utf-8?q?=3A_When_passing_the_re=2EDEBUG_flag=2C_re=2Ecompile=28=29_disp?= =?utf-8?q?lays_the_debug?= Message-ID: <3fJ0Zt4TcTz7LjN@mail.python.org> http://hg.python.org/cpython/rev/e47f6883dedf changeset: 88942:e47f6883dedf branch: 2.7 parent: 88936:129eb818d9b2 user: Antoine Pitrou date: Mon Feb 03 20:59:59 2014 +0100 summary: Issue #20426: When passing the re.DEBUG flag, re.compile() displays the debug output every time it is called, regardless of the compilation cache. files: Lib/re.py | 17 ++++++++++------- Lib/test/test_re.py | 14 ++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/Lib/re.py b/Lib/re.py --- a/Lib/re.py +++ b/Lib/re.py @@ -225,11 +225,13 @@ def _compile(*key): # internal: compile pattern - cachekey = (type(key[0]),) + key - p = _cache.get(cachekey) - if p is not None: - return p pattern, flags = key + bypass_cache = flags & DEBUG + if not bypass_cache: + cachekey = (type(key[0]),) + key + p = _cache.get(cachekey) + if p is not None: + return p if isinstance(pattern, _pattern_type): if flags: raise ValueError('Cannot process flags argument with a compiled pattern') @@ -240,9 +242,10 @@ p = sre_compile.compile(pattern, flags) except error, v: raise error, v # invalid expression - if len(_cache) >= _MAXCACHE: - _cache.clear() - _cache[cachekey] = p + if not bypass_cache: + if len(_cache) >= _MAXCACHE: + _cache.clear() + _cache[cachekey] = p return p def _compile_repl(*key): diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1,5 +1,6 @@ from test.test_support import verbose, run_unittest, import_module from test.test_support import precisionbigmemtest, _2G, cpython_only +from test.test_support import captured_stdout import re from re import Scanner import sre_constants @@ -920,6 +921,19 @@ self.assertEqual(m.group(1), "") self.assertEqual(m.group(2), "y") + def test_debug_flag(self): + with captured_stdout() as out: + re.compile('foo', re.DEBUG) + self.assertEqual(out.getvalue().splitlines(), + ['literal 102', 'literal 111', 'literal 111']) + # Debug output is output again even a second time (bypassing + # the cache -- issue #20426). + with captured_stdout() as out: + re.compile('foo', re.DEBUG) + self.assertEqual(out.getvalue().splitlines(), + ['literal 102', 'literal 111', 'literal 111']) + + def run_re_tests(): from test.re_tests import tests, SUCCEED, FAIL, SYNTAX_ERROR if verbose: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -38,6 +38,9 @@ Library ------- +- Issue #20426: When passing the re.DEBUG flag, re.compile() displays the + debug output every time it is called, regardless of the compilation cache. + - Issue #20368: The null character now correctly passed from Tcl to Python (in unicode strings only). Improved error handling in variables-related commands. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 21:32:51 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 21:32:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Skip_expr*_tes?= =?utf-8?q?ts_for_large_integers_for_Tcl_=3C8=2E5=2E?= Message-ID: <3fJ11v5sfLz7Ljd@mail.python.org> http://hg.python.org/cpython/rev/aed29f86bfdc changeset: 88943:aed29f86bfdc branch: 2.7 user: Serhiy Storchaka date: Mon Feb 03 22:30:22 2014 +0200 summary: Skip expr* tests for large integers for Tcl <8.5. The '**' operator is available only since 8.5 and in any case such large integers are not supported on Tcl <8.5. files: Lib/test/test_tcl.py | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -215,7 +215,6 @@ self.assertRaises(TclError, tcl.exprstring, 'spam') check('', '0') check('8.2 + 6', '14.2') - check('2**64', str(2**64)) check('3.1 + $a', '6.1') check('2 + "$a.$b"', '5.6') check('4*[llength "6 2"]', '8') @@ -233,6 +232,8 @@ check('"a\xc2\xbd\xe2\x82\xac"', 'a\xc2\xbd\xe2\x82\xac') check(r'"a\xbd\u20ac"', 'a\xc2\xbd\xe2\x82\xac') check(r'"a\0b"', 'a\xc0\x80b') + if tcl_version >= (8, 5): + check('2**64', str(2**64)) def test_exprdouble(self): tcl = self.interp @@ -248,7 +249,6 @@ self.assertRaises(TclError, tcl.exprdouble, 'spam') check('', 0.0) check('8.2 + 6', 14.2) - check('2**64', float(2**64)) check('3.1 + $a', 6.1) check('2 + "$a.$b"', 5.6) check('4*[llength "6 2"]', 8.0) @@ -263,6 +263,8 @@ check('[string length "a\xc2\xbd\xe2\x82\xac"]', 3.0) check(r'[string length "a\xbd\u20ac"]', 3.0) self.assertRaises(TclError, tcl.exprdouble, '"abc"') + if tcl_version >= (8, 5): + check('2**64', float(2**64)) def test_exprlong(self): tcl = self.interp @@ -278,7 +280,6 @@ self.assertRaises(TclError, tcl.exprlong, 'spam') check('', 0) check('8.2 + 6', 14) - self.assertRaises(TclError, tcl.exprlong, '2**64') check('3.1 + $a', 6) check('2 + "$a.$b"', 5) check('4*[llength "6 2"]', 8) @@ -293,6 +294,8 @@ check('[string length "a\xc2\xbd\xe2\x82\xac"]', 3) check(r'[string length "a\xbd\u20ac"]', 3) self.assertRaises(TclError, tcl.exprlong, '"abc"') + if tcl_version >= (8, 5): + self.assertRaises(TclError, tcl.exprlong, '2**64') def test_exprboolean(self): tcl = self.interp @@ -317,7 +320,6 @@ check('"%s"' % value, True) check('{%s}' % value, True) check('8.2 + 6', True) - check('2**64', True) check('3.1 + $a', True) check('2 + "$a.$b"', True) check('4*[llength "6 2"]', True) @@ -332,6 +334,8 @@ check('[string length "a\xc2\xbd\xe2\x82\xac"]', True) check(r'[string length "a\xbd\u20ac"]', True) self.assertRaises(TclError, tcl.exprboolean, '"abc"') + if tcl_version >= (8, 5): + check('2**64', True) def test_passing_values(self): def passValue(value): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 21:32:53 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 21:32:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Skip_expr*_tes?= =?utf-8?q?ts_for_large_integers_for_Tcl_=3C8=2E5=2E?= Message-ID: <3fJ11x0N5qz7LlC@mail.python.org> http://hg.python.org/cpython/rev/4f0e4a68dcdb changeset: 88944:4f0e4a68dcdb branch: 3.3 parent: 88940:a7b180d5df5f user: Serhiy Storchaka date: Mon Feb 03 22:31:09 2014 +0200 summary: Skip expr* tests for large integers for Tcl <8.5. The '**' operator is available only since 8.5 and in any case such large integers are not supported on Tcl <8.5. files: Lib/test/test_tcl.py | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -205,7 +205,6 @@ self.assertRaises(TclError, tcl.exprstring, 'spam') check('', '0') check('8.2 + 6', '14.2') - check('2**64', str(2**64)) check('3.1 + $a', '6.1') check('2 + "$a.$b"', '5.6') check('4*[llength "6 2"]', '8') @@ -223,6 +222,8 @@ check('"a\xbd\u20ac"', 'a\xbd\u20ac') check(r'"a\xbd\u20ac"', 'a\xbd\u20ac') check(r'"a\0b"', 'a\x00b') + if tcl_version >= (8, 5): + check('2**64', str(2**64)) def test_exprdouble(self): tcl = self.interp @@ -239,7 +240,6 @@ self.assertRaises(TclError, tcl.exprdouble, 'spam') check('', 0.0) check('8.2 + 6', 14.2) - check('2**64', float(2**64)) check('3.1 + $a', 6.1) check('2 + "$a.$b"', 5.6) check('4*[llength "6 2"]', 8.0) @@ -254,6 +254,8 @@ check('[string length "a\xbd\u20ac"]', 3.0) check(r'[string length "a\xbd\u20ac"]', 3.0) self.assertRaises(TclError, tcl.exprdouble, '"abc"') + if tcl_version >= (8, 5): + check('2**64', float(2**64)) def test_exprlong(self): tcl = self.interp @@ -270,7 +272,6 @@ self.assertRaises(TclError, tcl.exprlong, 'spam') check('', 0) check('8.2 + 6', 14) - self.assertRaises(TclError, tcl.exprlong, '2**64') check('3.1 + $a', 6) check('2 + "$a.$b"', 5) check('4*[llength "6 2"]', 8) @@ -285,6 +286,8 @@ check('[string length "a\xbd\u20ac"]', 3) check(r'[string length "a\xbd\u20ac"]', 3) self.assertRaises(TclError, tcl.exprlong, '"abc"') + if tcl_version >= (8, 5): + self.assertRaises(TclError, tcl.exprlong, '2**64') def test_exprboolean(self): tcl = self.interp @@ -310,7 +313,6 @@ check('"%s"' % value, True) check('{%s}' % value, True) check('8.2 + 6', True) - check('2**64', True) check('3.1 + $a', True) check('2 + "$a.$b"', True) check('4*[llength "6 2"]', True) @@ -325,6 +327,8 @@ check('[string length "a\xbd\u20ac"]', True) check(r'[string length "a\xbd\u20ac"]', True) self.assertRaises(TclError, tcl.exprboolean, '"abc"') + if tcl_version >= (8, 5): + check('2**64', True) def test_passing_values(self): def passValue(value): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 21:32:54 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 3 Feb 2014 21:32:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Skip_expr*_tests_for_large_integers_for_Tcl_=3C8=2E5=2E?= Message-ID: <3fJ11y2FjLz7LlC@mail.python.org> http://hg.python.org/cpython/rev/a5a622309a0b changeset: 88945:a5a622309a0b parent: 88941:a8bcfa290e68 parent: 88944:4f0e4a68dcdb user: Serhiy Storchaka date: Mon Feb 03 22:32:00 2014 +0200 summary: Skip expr* tests for large integers for Tcl <8.5. The '**' operator is available only since 8.5 and in any case such large integers are not supported on Tcl <8.5. files: Lib/test/test_tcl.py | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -205,7 +205,6 @@ self.assertRaises(TclError, tcl.exprstring, 'spam') check('', '0') check('8.2 + 6', '14.2') - check('2**64', str(2**64)) check('3.1 + $a', '6.1') check('2 + "$a.$b"', '5.6') check('4*[llength "6 2"]', '8') @@ -223,6 +222,8 @@ check('"a\xbd\u20ac"', 'a\xbd\u20ac') check(r'"a\xbd\u20ac"', 'a\xbd\u20ac') check(r'"a\0b"', 'a\x00b') + if tcl_version >= (8, 5): + check('2**64', str(2**64)) def test_exprdouble(self): tcl = self.interp @@ -239,7 +240,6 @@ self.assertRaises(TclError, tcl.exprdouble, 'spam') check('', 0.0) check('8.2 + 6', 14.2) - check('2**64', float(2**64)) check('3.1 + $a', 6.1) check('2 + "$a.$b"', 5.6) check('4*[llength "6 2"]', 8.0) @@ -254,6 +254,8 @@ check('[string length "a\xbd\u20ac"]', 3.0) check(r'[string length "a\xbd\u20ac"]', 3.0) self.assertRaises(TclError, tcl.exprdouble, '"abc"') + if tcl_version >= (8, 5): + check('2**64', float(2**64)) def test_exprlong(self): tcl = self.interp @@ -270,7 +272,6 @@ self.assertRaises(TclError, tcl.exprlong, 'spam') check('', 0) check('8.2 + 6', 14) - self.assertRaises(TclError, tcl.exprlong, '2**64') check('3.1 + $a', 6) check('2 + "$a.$b"', 5) check('4*[llength "6 2"]', 8) @@ -285,6 +286,8 @@ check('[string length "a\xbd\u20ac"]', 3) check(r'[string length "a\xbd\u20ac"]', 3) self.assertRaises(TclError, tcl.exprlong, '"abc"') + if tcl_version >= (8, 5): + self.assertRaises(TclError, tcl.exprlong, '2**64') def test_exprboolean(self): tcl = self.interp @@ -310,7 +313,6 @@ check('"%s"' % value, True) check('{%s}' % value, True) check('8.2 + 6', True) - check('2**64', True) check('3.1 + $a', True) check('2 + "$a.$b"', True) check('4*[llength "6 2"]', True) @@ -325,6 +327,8 @@ check('[string length "a\xbd\u20ac"]', True) check(r'[string length "a\xbd\u20ac"]', True) self.assertRaises(TclError, tcl.exprboolean, '"abc"') + if tcl_version >= (8, 5): + check('2**64', True) def test_passing_values(self): def passValue(value): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 23:02:56 2014 From: python-checkins at python.org (ned.deily) Date: Mon, 3 Feb 2014 23:02:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNDc0?= =?utf-8?q?=3A_Fix_=22unexpected_success=22_test=5Fsocket_failures_on_OS_X?= =?utf-8?q?_10=2E7+=2E?= Message-ID: <3fJ31r08n3z7LjV@mail.python.org> http://hg.python.org/cpython/rev/63efacd80f8e changeset: 88946:63efacd80f8e branch: 3.3 parent: 88944:4f0e4a68dcdb user: Ned Deily date: Mon Feb 03 13:58:31 2014 -0800 summary: Issue #20474: Fix "unexpected success" test_socket failures on OS X 10.7+. files: Lib/test/test_socket.py | 8 ++++---- Misc/NEWS | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -3490,12 +3490,12 @@ self.assertNotIsInstance(cm.exception, socket.timeout) self.assertEqual(cm.exception.errno, errno.EINTR) - # Issue #12958: The following tests have problems on Mac OS X - @support.anticipate_failure(sys.platform == "darwin") + # Issue #12958: The following tests have problems on OS X prior to 10.7 + @support.requires_mac_ver(10, 7) def testInterruptedSendTimeout(self): self.checkInterruptedSend(self.serv_conn.send, b"a"*512) - @support.anticipate_failure(sys.platform == "darwin") + @support.requires_mac_ver(10, 7) def testInterruptedSendtoTimeout(self): # Passing an actual address here as Python's wrapper for # sendto() doesn't allow passing a zero-length one; POSIX @@ -3504,7 +3504,7 @@ self.checkInterruptedSend(self.serv_conn.sendto, b"a"*512, self.serv_addr) - @support.anticipate_failure(sys.platform == "darwin") + @support.requires_mac_ver(10, 7) @requireAttrs(socket.socket, "sendmsg") def testInterruptedSendmsgTimeout(self): self.checkInterruptedSend(self.serv_conn.sendmsg, [b"a"*512]) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -365,6 +365,8 @@ - Issue #19085: Added basic tests for all tkinter widget options. +- Issue #20474: Fix test_socket "unexpected success" failures on OS X 10.7+. + Documentation ------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 23:02:57 2014 From: python-checkins at python.org (ned.deily) Date: Mon, 3 Feb 2014 23:02:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320474=3A_Fix_=22unexpected_success=22_test=5Fso?= =?utf-8?q?cket_failures_on_OS_X_10=2E7+=2E?= Message-ID: <3fJ31s2Jl4z7LkQ@mail.python.org> http://hg.python.org/cpython/rev/036671354dc0 changeset: 88947:036671354dc0 parent: 88945:a5a622309a0b parent: 88946:63efacd80f8e user: Ned Deily date: Mon Feb 03 14:02:26 2014 -0800 summary: Issue #20474: Fix "unexpected success" test_socket failures on OS X 10.7+. files: Lib/test/test_socket.py | 8 ++++---- Misc/NEWS | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -3635,12 +3635,12 @@ self.assertNotIsInstance(cm.exception, socket.timeout) self.assertEqual(cm.exception.errno, errno.EINTR) - # Issue #12958: The following tests have problems on Mac OS X - @support.anticipate_failure(sys.platform == "darwin") + # Issue #12958: The following tests have problems on OS X prior to 10.7 + @support.requires_mac_ver(10, 7) def testInterruptedSendTimeout(self): self.checkInterruptedSend(self.serv_conn.send, b"a"*512) - @support.anticipate_failure(sys.platform == "darwin") + @support.requires_mac_ver(10, 7) def testInterruptedSendtoTimeout(self): # Passing an actual address here as Python's wrapper for # sendto() doesn't allow passing a zero-length one; POSIX @@ -3649,7 +3649,7 @@ self.checkInterruptedSend(self.serv_conn.sendto, b"a"*512, self.serv_addr) - @support.anticipate_failure(sys.platform == "darwin") + @support.requires_mac_ver(10, 7) @requireAttrs(socket.socket, "sendmsg") def testInterruptedSendmsgTimeout(self): self.checkInterruptedSend(self.serv_conn.sendmsg, [b"a"*512]) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -106,6 +106,8 @@ - Issue #19990: Added tests for the imghdr module. Based on patch by Claudiu Popa. +- Issue #20474: Fix test_socket "unexpected success" failures on OS X 10.7+. + Tools/Demos ----------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 23:26:44 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 3 Feb 2014 23:26:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Esubprocess=3A_Re?= =?utf-8?q?place_Process=2Eget=5Fsubprocess=28=29_method_with_a?= Message-ID: <3fJ3YJ6v1wz7Llg@mail.python.org> http://hg.python.org/cpython/rev/47cfd0980020 changeset: 88948:47cfd0980020 user: Victor Stinner date: Mon Feb 03 23:08:14 2014 +0100 summary: asyncio.subprocess: Replace Process.get_subprocess() method with a Process.subprocess read-only property files: Doc/library/asyncio-subprocess.rst | 34 ++++++------ Lib/asyncio/subprocess.py | 3 +- Lib/test/test_asyncio/test_subprocess.py | 16 ++-- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -57,6 +57,21 @@ .. class:: asyncio.subprocess.Process + .. attribute:: pid + + The identifier of the process. + + Note that if you set the *shell* argument to ``True``, this is the + process identifier of the spawned shell. + + .. attribute:: returncode + + Return code of the process when it exited. A ``None`` value indicates + that the process has not terminated yet. + + A negative value ``-N`` indicates that the child was terminated by signal + ``N`` (Unix only). + .. attribute:: stdin Standard input stream (write), ``None`` if the process was created with @@ -72,20 +87,9 @@ Standard error stream (read), ``None`` if the process was created with ``stderr=None``. - .. attribute:: pid + .. attribute:: subprocess - The identifier of the process. - - Note that if you set the *shell* argument to ``True``, this is the - process identifier of the spawned shell. - - .. attribute:: returncode - - Return code of the process when it exited. A ``None`` value indicates - that the process has not terminated yet. - - A negative value ``-N`` indicates that the child was terminated by signal - ``N`` (Unix only). + Underlying :class:`subprocess.Popen` object. .. method:: communicate(input=None) @@ -107,10 +111,6 @@ The data read is buffered in memory, so do not use this method if the data size is large or unlimited. - .. method:: get_subprocess() - - Get the underlying :class:`subprocess.Popen` object. - .. method:: kill() Kills the child. On Posix OSs the function sends :py:data:`SIGKILL` to diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -106,7 +106,8 @@ yield from waiter return waiter.result() - def get_subprocess(self): + @property + def subprocess(self): return self._transport.get_extra_info('subprocess') def _check_alive(self): diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -119,7 +119,7 @@ returncode = self.loop.run_until_complete(proc.wait()) self.assertEqual(-signal.SIGHUP, returncode) - def test_get_subprocess(self): + def test_subprocess(self): args = PROGRAM_EXIT_FAST @asyncio.coroutine @@ -127,14 +127,14 @@ proc = yield from asyncio.create_subprocess_exec(*args, loop=self.loop) yield from proc.wait() + # need to poll subprocess.Popen, otherwise the returncode + # attribute is not set + proc.subprocess.wait() + return proc - popen = proc.get_subprocess() - popen.wait() - return (proc, popen) - - proc, popen = self.loop.run_until_complete(run()) - self.assertEqual(popen.returncode, proc.returncode) - self.assertEqual(popen.pid, proc.pid) + proc = self.loop.run_until_complete(run()) + self.assertEqual(proc.subprocess.returncode, proc.returncode) + self.assertEqual(proc.subprocess.pid, proc.pid) def test_broken_pipe(self): large_data = b'x' * support.PIPE_MAX_SIZE -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 3 23:26:46 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 3 Feb 2014 23:26:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_add_an_exam?= =?utf-8?q?ple_of_asyncio=2Esubprocess_with_communicate=28=29_and_wait=28?= =?utf-8?q?=29?= Message-ID: <3fJ3YL1V94z7Lld@mail.python.org> http://hg.python.org/cpython/rev/0c2f707473fc changeset: 88949:0c2f707473fc user: Victor Stinner date: Mon Feb 03 23:26:28 2014 +0100 summary: asyncio doc: add an example of asyncio.subprocess with communicate() and wait() files: Doc/library/asyncio-subprocess.rst | 40 ++++++++++++++++++ 1 files changed, 40 insertions(+), 0 deletions(-) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -138,3 +138,43 @@ Wait for child process to terminate. Set and return :attr:`returncode` attribute. + +Example +------- + +Implement a function similar to :func:`subprocess.getstatusoutput`, except that +it does not use a shell. Get the output of the "python -m platform" command and +display the output:: + + import asyncio + import sys + from asyncio import subprocess + + @asyncio.coroutine + def getstatusoutput(*args): + proc = yield from asyncio.create_subprocess_exec( + *args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + try: + stdout, _ = yield from proc.communicate() + except: + proc.kill() + yield from proc.wait() + raise + exitcode = yield from proc.wait() + return (exitcode, stdout) + + loop = asyncio.get_event_loop() + coro = getstatusoutput(sys.executable, '-m', 'platform') + exitcode, stdout = loop.run_until_complete(coro) + if not exitcode: + stdout = stdout.decode('ascii').rstrip() + print("Platform: %s" % stdout) + else: + print("Python failed with exit code %s:" % exitcode) + sys.stdout.flush() + sys.stdout.buffer.flush() + sys.stdout.buffer.write(stdout) + sys.stdout.buffer.flush() + loop.close() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 00:04:22 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 4 Feb 2014 00:04:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Oops=2C_undo_unwanted_chan?= =?utf-8?q?ges_in_test=5Fasyncio=3A_mistakes_of_my_the_last_sync_with?= Message-ID: <3fJ4Nk0RZfz7LjV@mail.python.org> http://hg.python.org/cpython/rev/d7dc5ebc33ef changeset: 88950:d7dc5ebc33ef user: Victor Stinner date: Mon Feb 03 23:59:52 2014 +0100 summary: Oops, undo unwanted changes in test_asyncio: mistakes of my the last sync with Tulip (changeset d7ac90c0463a) files: Lib/test/test_asyncio/test_base_events.py | 15 +++++---- Lib/test/test_asyncio/test_events.py | 8 +++++ Lib/test/test_asyncio/test_windows_events.py | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -116,17 +116,18 @@ self.loop.stop() self.loop._process_events = unittest.mock.Mock() - when = self.loop.time() + 0.1 + delay = 0.1 + + when = self.loop.time() + delay self.loop.call_at(when, cb) t0 = self.loop.time() self.loop.run_forever() dt = self.loop.time() - t0 - self.assertTrue(0.09 <= dt <= 0.9, - # Issue #20452: add more info in case of failure, - # to try to investigate the bug - (dt, - self.loop._granularity, - time.get_clock_info('monotonic'))) + + self.assertGreaterEqual(dt, delay - self.loop._granularity, dt) + # tolerate a difference of +800 ms because some Python buildbots + # are really slow + self.assertLessEqual(dt, 0.9, dt) def test_run_once_in_executor_handle(self): def cb(): diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1185,6 +1185,14 @@ calls.append(self.loop._run_once_counter) self.assertEqual(calls, [1, 3, 5, 6]) + def test_granularity(self): + granularity = self.loop._granularity + self.assertGreater(granularity, 0.0) + # Worst expected granularity: 1 ms on Linux (limited by poll/epoll + # resolution), 15.6 ms on Windows (limited by time.monotonic + # resolution) + self.assertLess(granularity, 0.050) + class SubprocessTestsMixin: diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -105,7 +105,7 @@ self.loop.run_until_complete(f) elapsed = self.loop.time() - start self.assertFalse(f.result()) - self.assertTrue(0.18 < elapsed < 0.5, elapsed) + self.assertTrue(0.18 < elapsed < 0.9, elapsed) _overlapped.SetEvent(event) -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Tue Feb 4 09:12:54 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 04 Feb 2014 09:12:54 +0100 Subject: [Python-checkins] Daily reference leaks (d7dc5ebc33ef): sum=-13 Message-ID: results for d7dc5ebc33ef on branch "default" -------------------------------------------- test_site leaked [-2, 2, -2] references, sum=-2 test_site leaked [-2, 2, -2] memory blocks, sum=-2 test_urllib2net leaked [1590, -1601, 0] references, sum=-11 test_urllib2net leaked [1409, -1409, 2] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog1VaOpl', '-x'] From python-checkins at python.org Tue Feb 4 09:26:12 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 4 Feb 2014 09:26:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Fix_=5FProactor?= =?utf-8?q?WritePipeTransport=2E=5Fpipe=5Fclosed=28=29?= Message-ID: <3fJJs044Hcz7LjP@mail.python.org> http://hg.python.org/cpython/rev/632ff061636b changeset: 88951:632ff061636b user: Victor Stinner date: Tue Feb 04 08:57:48 2014 +0100 summary: asyncio: Fix _ProactorWritePipeTransport._pipe_closed() Do nothing if the pipe is already closed. _loop_writing() may call _force_close() when it gets ConnectionResetError. files: Lib/asyncio/proactor_events.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -304,9 +304,12 @@ if fut.cancelled(): # the transport has been closed return + assert fut.result() == b'' + if self._closing: + assert self._read_fut is None + return assert fut is self._read_fut, (fut, self._read_fut) self._read_fut = None - assert fut.result() == b'' if self._write_fut is not None: self._force_close(exc) else: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 09:33:23 2014 From: python-checkins at python.org (martin.v.loewis) Date: Tue, 4 Feb 2014 09:33:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317162=3A_Add_PyTy?= =?utf-8?q?pe=5FGetSlot=2E?= Message-ID: <3fJK1H0w8Cz7Ljd@mail.python.org> http://hg.python.org/cpython/rev/655d7a55c165 changeset: 88952:655d7a55c165 user: Martin v. L?wis date: Tue Feb 04 09:33:05 2014 +0100 summary: Issue #17162: Add PyType_GetSlot. files: Doc/c-api/type.rst | 10 ++++++++++ Include/object.h | 3 +++ Misc/NEWS | 2 ++ Modules/xxlimited.c | 2 +- Objects/typeobject.c | 13 +++++++++++++ setup.py | 2 +- 6 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -97,3 +97,13 @@ types. This allows the caller to reference other heap types as base types. .. versionadded:: 3.3 + +.. c:function:: void* PyType_GetSlot(PyTypeObject *type, int slot) + + Return the function pointer stored int the given slot. If the + result is *NULL*, this indicates that either the slot is *NULL*, + or that the function was called with invalid parameters. + Callers will typically cast the result pointer into the appropriate + function type. + + .. versionadded:: 3.4 diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -439,6 +439,9 @@ #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03030000 PyAPI_FUNC(PyObject*) PyType_FromSpecWithBases(PyType_Spec*, PyObject*); #endif +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03040000 +PyAPI_FUNC(void*) PyType_GetSlot(PyTypeObject*, int); +#endif #ifndef Py_LIMITED_API /* The *real* layout of a type object when allocated on the heap */ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #17162: Add PyType_GetSlot. + - Issue #20162: Fix an alignment issue in the siphash24() hash function which caused a crash on PowerPC 64-bit (ppc64). diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -44,7 +44,7 @@ Xxo_dealloc(XxoObject *self) { Py_XDECREF(self->x_attr); - PyObject_Del(self); + ((freefunc)PyType_GetSlot(Py_TYPE(self), Py_tp_free))(self); } static PyObject * diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2641,6 +2641,19 @@ return PyType_FromSpecWithBases(spec, NULL); } +void * +PyType_GetSlot(PyTypeObject *type, int slot) +{ + if (!PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE))?{ + PyErr_BadInternalCall(); + return NULL; + } + if (slot >= Py_ARRAY_LENGTH(slotoffsets)) { + /* Extension module requesting slot from a future version */ + return NULL; + } + return *(void**)(((char*)type) + slotoffsets[slot]); +} /* Internal API to look for a name through the MRO. This returns a borrowed reference, and doesn't set an exception! */ diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -1539,7 +1539,7 @@ if 'd' not in sys.abiflags: ext = Extension('xxlimited', ['xxlimited.c'], - define_macros=[('Py_LIMITED_API', 1)]) + define_macros=[('Py_LIMITED_API', '0x03040000')]) self.extensions.append(ext) return missing -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 09:49:30 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 4 Feb 2014 09:49:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2317162=3A_Fix_comp?= =?utf-8?q?ilation=2C_replace_non-breaking_space_with_an_ASCII_space?= Message-ID: <3fJKMt2p1Mz7LjV@mail.python.org> http://hg.python.org/cpython/rev/eaae4008327d changeset: 88953:eaae4008327d user: Victor Stinner date: Tue Feb 04 09:49:14 2014 +0100 summary: Issue #17162: Fix compilation, replace non-breaking space with an ASCII space files: Objects/typeobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2644,7 +2644,7 @@ void * PyType_GetSlot(PyTypeObject *type, int slot) { - if (!PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE))?{ + if (!PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { PyErr_BadInternalCall(); return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 13:14:11 2014 From: python-checkins at python.org (nick.coghlan) Date: Tue, 4 Feb 2014 13:14:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320404=3A_blacklis?= =?utf-8?q?t_non-text_encodings_in_io=2ETextIOWrapper?= Message-ID: <3fJPw36rf0z7LkY@mail.python.org> http://hg.python.org/cpython/rev/f3ec00d2b75e changeset: 88954:f3ec00d2b75e user: Nick Coghlan date: Tue Feb 04 22:11:18 2014 +1000 summary: Close #20404: blacklist non-text encodings in io.TextIOWrapper - io.TextIOWrapper (and hence the open() builtin) now use the internal codec marking system added for issue #19619 - also tweaked the C code to only look up the encoding once, rather than multiple times - the existing output type checks remain in place to deal with unmarked third party codecs. files: Include/codecs.h | 20 +++++++ Lib/_pyio.py | 5 + Lib/test/test_io.py | 33 +++++++++-- Misc/NEWS | 6 ++ Modules/_io/textio.c | 34 ++++++++---- Python/codecs.c | 88 +++++++++++++++++++++++-------- 6 files changed, 143 insertions(+), 43 deletions(-) diff --git a/Include/codecs.h b/Include/codecs.h --- a/Include/codecs.h +++ b/Include/codecs.h @@ -104,7 +104,14 @@ Please note that these APIs are internal and should not be used in Python C extensions. + XXX (ncoghlan): should we make these, or something like them, public + in Python 3.5+? + */ +PyAPI_FUNC(PyObject *) _PyCodec_LookupTextEncoding( + const char *encoding, + const char *alternate_command + ); PyAPI_FUNC(PyObject *) _PyCodec_EncodeText( PyObject *object, @@ -117,6 +124,19 @@ const char *encoding, const char *errors ); + +/* These two aren't actually text encoding specific, but _io.TextIOWrapper + * is the only current API consumer. + */ +PyAPI_FUNC(PyObject *) _PyCodecInfo_GetIncrementalDecoder( + PyObject *codec_info, + const char *errors + ); + +PyAPI_FUNC(PyObject *) _PyCodecInfo_GetIncrementalEncoder( + PyObject *codec_info, + const char *errors + ); #endif diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -1503,6 +1503,11 @@ if not isinstance(encoding, str): raise ValueError("invalid encoding: %r" % encoding) + if not codecs.lookup(encoding)._is_text_encoding: + msg = ("%r is not a text encoding; " + "use codecs.open() to handle arbitrary codecs") + raise LookupError(msg % encoding) + if errors is None: errors = "strict" else: diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1929,6 +1929,15 @@ self.assertRaises(TypeError, t.__init__, b, newline=42) self.assertRaises(ValueError, t.__init__, b, newline='xyzzy') + def test_non_text_encoding_codecs_are_rejected(self): + # Ensure the constructor complains if passed a codec that isn't + # marked as a text encoding + # http://bugs.python.org/issue20404 + r = self.BytesIO() + b = self.BufferedWriter(r) + with self.assertRaisesRegex(LookupError, "is not a text encoding"): + self.TextIOWrapper(b, encoding="hex") + def test_detach(self): r = self.BytesIO() b = self.BufferedWriter(r) @@ -2579,15 +2588,22 @@ def test_illegal_decoder(self): # Issue #17106 + # Bypass the early encoding check added in issue 20404 + def _make_illegal_wrapper(): + quopri = codecs.lookup("quopri") + quopri._is_text_encoding = True + try: + t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), + newline='\n', encoding="quopri") + finally: + quopri._is_text_encoding = False + return t # Crash when decoder returns non-string - t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), newline='\n', - encoding='quopri_codec') + t = _make_illegal_wrapper() self.assertRaises(TypeError, t.read, 1) - t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), newline='\n', - encoding='quopri_codec') + t = _make_illegal_wrapper() self.assertRaises(TypeError, t.readline) - t = self.TextIOWrapper(self.BytesIO(b'aaaaaa'), newline='\n', - encoding='quopri_codec') + t = _make_illegal_wrapper() self.assertRaises(TypeError, t.read) def _check_create_at_shutdown(self, **kwargs): @@ -2616,8 +2632,7 @@ if err: # Can error out with a RuntimeError if the module state # isn't found. - self.assertIn("RuntimeError: could not find io module state", - err.decode()) + self.assertIn(self.shutdown_error, err.decode()) else: self.assertEqual("ok", out.decode().strip()) @@ -2630,6 +2645,7 @@ class CTextIOWrapperTest(TextIOWrapperTest): io = io + shutdown_error = "RuntimeError: could not find io module state" def test_initialization(self): r = self.BytesIO(b"\xc3\xa9\n\n") @@ -2674,6 +2690,7 @@ class PyTextIOWrapperTest(TextIOWrapperTest): io = pyio + shutdown_error = "LookupError: unknown encoding: ascii" class IncrementalNewlineDecoderTest(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,12 @@ Core and Builtins ----------------- +- Issue #20404: io.TextIOWrapper (and hence the open() builtin) now uses the + internal codec marking system added for issue #19619 to throw LookupError + for known non-text encodings at stream construction time. The existing + output type checks remain in place to deal with unmarked third party + codecs. + - Issue #17162: Add PyType_GetSlot. - Issue #20162: Fix an alignment issue in the siphash24() hash function which diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -849,7 +849,7 @@ char *kwlist[] = {"buffer", "encoding", "errors", "newline", "line_buffering", "write_through", NULL}; - PyObject *buffer, *raw; + PyObject *buffer, *raw, *codec_info = NULL; char *encoding = NULL; char *errors = NULL; char *newline = NULL; @@ -961,6 +961,17 @@ "could not determine default encoding"); } + /* Check we have been asked for a real text encoding */ + codec_info = _PyCodec_LookupTextEncoding(encoding, "codecs.open()"); + if (codec_info == NULL) { + Py_CLEAR(self->encoding); + goto error; + } + + /* XXX: Failures beyond this point have the potential to leak elements + * of the partially constructed object (like self->encoding) + */ + if (errors == NULL) errors = "strict"; self->errors = PyBytes_FromString(errors); @@ -975,7 +986,7 @@ if (newline) { self->readnl = PyUnicode_FromString(newline); if (self->readnl == NULL) - return -1; + goto error; } self->writetranslate = (newline == NULL || newline[0] != '\0'); if (!self->readuniversal && self->readnl) { @@ -999,8 +1010,8 @@ if (r == -1) goto error; if (r == 1) { - self->decoder = PyCodec_IncrementalDecoder( - encoding, errors); + self->decoder = _PyCodecInfo_GetIncrementalDecoder(codec_info, + errors); if (self->decoder == NULL) goto error; @@ -1024,17 +1035,12 @@ if (r == -1) goto error; if (r == 1) { - PyObject *ci; - self->encoder = PyCodec_IncrementalEncoder( - encoding, errors); + self->encoder = _PyCodecInfo_GetIncrementalEncoder(codec_info, + errors); if (self->encoder == NULL) goto error; /* Get the normalized named of the codec */ - ci = _PyCodec_Lookup(encoding); - if (ci == NULL) - goto error; - res = _PyObject_GetAttrId(ci, &PyId_name); - Py_DECREF(ci); + res = _PyObject_GetAttrId(codec_info, &PyId_name); if (res == NULL) { if (PyErr_ExceptionMatches(PyExc_AttributeError)) PyErr_Clear(); @@ -1054,6 +1060,9 @@ Py_XDECREF(res); } + /* Finished sorting out the codec details */ + Py_DECREF(codec_info); + self->buffer = buffer; Py_INCREF(buffer); @@ -1116,6 +1125,7 @@ return 0; error: + Py_XDECREF(codec_info); return -1; } diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -243,20 +243,15 @@ return v; } -/* Helper function to create an incremental codec. */ +/* Helper functions to create an incremental codec. */ +static +PyObject *codec_makeincrementalcodec(PyObject *codec_info, + const char *errors, + const char *attrname) +{ + PyObject *ret, *inccodec; -static -PyObject *codec_getincrementalcodec(const char *encoding, - const char *errors, - const char *attrname) -{ - PyObject *codecs, *ret, *inccodec; - - codecs = _PyCodec_Lookup(encoding); - if (codecs == NULL) - return NULL; - inccodec = PyObject_GetAttrString(codecs, attrname); - Py_DECREF(codecs); + inccodec = PyObject_GetAttrString(codec_info, attrname); if (inccodec == NULL) return NULL; if (errors) @@ -267,6 +262,21 @@ return ret; } +static +PyObject *codec_getincrementalcodec(const char *encoding, + const char *errors, + const char *attrname) +{ + PyObject *codec_info, *ret; + + codec_info = _PyCodec_Lookup(encoding); + if (codec_info == NULL) + return NULL; + ret = codec_makeincrementalcodec(codec_info, errors, attrname); + Py_DECREF(codec_info); + return ret; +} + /* Helper function to create a stream codec. */ static @@ -290,6 +300,24 @@ return streamcodec; } +/* Helpers to work with the result of _PyCodec_Lookup + + */ +PyObject *_PyCodecInfo_GetIncrementalDecoder(PyObject *codec_info, + const char *errors) +{ + return codec_makeincrementalcodec(codec_info, errors, + "incrementaldecoder"); +} + +PyObject *_PyCodecInfo_GetIncrementalEncoder(PyObject *codec_info, + const char *errors) +{ + return codec_makeincrementalcodec(codec_info, errors, + "incrementalencoder"); +} + + /* Convenience APIs to query the Codec registry. All APIs return a codec object with incremented refcount. @@ -467,15 +495,12 @@ } /* Text encoding/decoding API */ -static -PyObject *codec_getitem_checked(const char *encoding, - const char *operation_name, - int index) +PyObject * _PyCodec_LookupTextEncoding(const char *encoding, + const char *alternate_command) { _Py_IDENTIFIER(_is_text_encoding); PyObject *codec; PyObject *attr; - PyObject *v; int is_text_codec; codec = _PyCodec_Lookup(encoding); @@ -502,27 +527,44 @@ Py_DECREF(codec); PyErr_Format(PyExc_LookupError, "'%.400s' is not a text encoding; " - "use codecs.%s() to handle arbitrary codecs", - encoding, operation_name); + "use %s to handle arbitrary codecs", + encoding, alternate_command); return NULL; } } } + /* This appears to be a valid text encoding */ + return codec; +} + + +static +PyObject *codec_getitem_checked(const char *encoding, + const char *alternate_command, + int index) +{ + PyObject *codec; + PyObject *v; + + codec = _PyCodec_LookupTextEncoding(encoding, alternate_command); + if (codec == NULL) + return NULL; + v = PyTuple_GET_ITEM(codec, index); + Py_INCREF(v); Py_DECREF(codec); - Py_INCREF(v); return v; } static PyObject * _PyCodec_TextEncoder(const char *encoding) { - return codec_getitem_checked(encoding, "encode", 0); + return codec_getitem_checked(encoding, "codecs.encode()", 0); } static PyObject * _PyCodec_TextDecoder(const char *encoding) { - return codec_getitem_checked(encoding, "decode", 1); + return codec_getitem_checked(encoding, "codecs.decode()", 1); } PyObject *_PyCodec_EncodeText(PyObject *object, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 14:03:01 2014 From: python-checkins at python.org (nick.coghlan) Date: Tue, 4 Feb 2014 14:03:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320053=3A_ignore_d?= =?utf-8?q?efault_pip_config_settings?= Message-ID: <3fJR0P0KWbz7Lkt@mail.python.org> http://hg.python.org/cpython/rev/1b8ba1346e67 changeset: 88955:1b8ba1346e67 user: Nick Coghlan date: Tue Feb 04 23:02:36 2014 +1000 summary: Close #20053: ignore default pip config settings ensurepip now sets PIP_CONFIG_FILE to os.devnull before import pip from the wheel file. This also ensures venv ignores the default settings when bootstrapping pip. files: Lib/ensurepip/__init__.py | 9 ++++-- Lib/test/test_ensurepip.py | 16 +++++++++++ Lib/test/test_venv.py | 37 +++++++++++++++++++------ Misc/NEWS | 3 ++ 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -47,13 +47,16 @@ """ return _PIP_VERSION -def _clear_pip_environment_variables(): +def _disable_pip_configuration_settings(): # We deliberately ignore all pip environment variables # when invoking pip # See http://bugs.python.org/issue19734 for details keys_to_remove = [k for k in os.environ if k.startswith("PIP_")] for k in keys_to_remove: del os.environ[k] + # We also ignore the settings in the default pip configuration file + # See http://bugs.python.org/issue20053 for details + os.environ['PIP_CONFIG_FILE'] = os.devnull def bootstrap(*, root=None, upgrade=False, user=False, @@ -69,7 +72,7 @@ raise ValueError("Cannot use altinstall and default_pip together") _require_ssl_for_pip() - _clear_pip_environment_variables() + _disable_pip_configuration_settings() # By default, installing pip and setuptools installs all of the # following scripts (X.Y == running Python version): @@ -130,7 +133,7 @@ raise RuntimeError(msg.format(pip.__version__, _PIP_VERSION)) _require_ssl_for_pip() - _clear_pip_environment_variables() + _disable_pip_configuration_settings() # Construct the arguments to be passed to the pip command args = ["uninstall", "-y"] diff --git a/Lib/test/test_ensurepip.py b/Lib/test/test_ensurepip.py --- a/Lib/test/test_ensurepip.py +++ b/Lib/test/test_ensurepip.py @@ -36,9 +36,11 @@ self.addCleanup(run_pip_patch.stop) # Avoid side effects on the actual os module + real_devnull = os.devnull os_patch = unittest.mock.patch("ensurepip.os") patched_os = os_patch.start() self.addCleanup(os_patch.stop) + patched_os.devnull = real_devnull patched_os.path = os.path self.os_environ = patched_os.environ = os.environ.copy() @@ -161,6 +163,12 @@ ensurepip.bootstrap() self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ) + @requires_usable_pip + def test_pip_config_file_disabled(self): + # ensurepip deliberately ignores the pip config file + # See http://bugs.python.org/issue20053 for details + ensurepip.bootstrap() + self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull) @contextlib.contextmanager def fake_pip(version=ensurepip._PIP_VERSION): @@ -240,6 +248,14 @@ ensurepip._uninstall_helper() self.assertNotIn("PIP_THIS_SHOULD_GO_AWAY", self.os_environ) + @requires_usable_pip + def test_pip_config_file_disabled(self): + # ensurepip deliberately ignores the pip config file + # See http://bugs.python.org/issue20053 for details + with fake_pip(): + ensurepip._uninstall_helper() + self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull) + class TestMissingSSL(EnsurepipMixin, unittest.TestCase): diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -301,16 +301,35 @@ # that we want to ensure it ignores the normal pip environment # variable settings. We set PIP_NO_INSTALL here specifically # to check that ensurepip (and hence venv) ignores it. - # See http://bugs.python.org/issue19734 for details + # See http://bugs.python.org/issue19734 envvars["PIP_NO_INSTALL"] = "1" - try: - self.run_with_capture(venv.create, self.env_dir, with_pip=True) - except subprocess.CalledProcessError as exc: - # The output this produces can be a little hard to read, but - # least it has all the details - details = exc.output.decode(errors="replace") - msg = "{}\n\n**Subprocess Output**\n{}".format(exc, details) - self.fail(msg) + # Also check that we ignore the pip configuration file + # See http://bugs.python.org/issue20053 + with tempfile.TemporaryDirectory() as home_dir: + envvars["HOME"] = home_dir + bad_config = "[global]\nno-install=1" + # Write to both config file names on all platforms to reduce + # cross-platform variation in test code behaviour + win_location = ("pip", "pip.ini") + posix_location = (".pip", "pip.conf") + for dirname, fname in (win_location, posix_location): + dirpath = os.path.join(home_dir, dirname) + os.mkdir(dirpath) + fpath = os.path.join(dirpath, fname) + with open(fpath, 'w') as f: + f.write(bad_config) + + # Actually run the create command with all that unhelpful + # config in place to ensure we ignore it + try: + self.run_with_capture(venv.create, self.env_dir, + with_pip=True) + except subprocess.CalledProcessError as exc: + # The output this produces can be a little hard to read, + # but at least it has all the details + details = exc.output.decode(errors="replace") + msg = "{}\n\n**Subprocess Output**\n{}" + self.fail(msg.format(exc, details)) # Ensure pip is available in the virtual environment envpy = os.path.join(os.path.realpath(self.env_dir), self.bindir, self.exe) cmd = [envpy, '-Im', 'pip', '--version'] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,9 @@ Library ------- +- Issue #20053: ensurepip (and hence venv) are no longer affected by the + settings in the default pip configuration file. + - Issue #20426: When passing the re.DEBUG flag, re.compile() displays the debug output every time it is called, regardless of the compilation cache. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 16:12:26 2014 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 4 Feb 2014 16:12:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_restore_namesp?= =?utf-8?q?acing_of_pyexpat_symbols_=28closes_=2319186=29?= Message-ID: <3fJTsk75JRz7LkX@mail.python.org> http://hg.python.org/cpython/rev/c242a8f30806 changeset: 88956:c242a8f30806 branch: 3.3 parent: 88946:63efacd80f8e user: Benjamin Peterson date: Tue Feb 04 10:10:55 2014 -0500 summary: restore namespacing of pyexpat symbols (closes #19186) files: Misc/NEWS | 2 ++ Modules/expat/expat_external.h | 4 ++++ 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,8 @@ Library ------- +- Issue #19186: Restore namespacing of expat symbols inside the pyexpat module. + - Issue #20426: When passing the re.DEBUG flag, re.compile() displays the debug output every time it is called, regardless of the compilation cache. diff --git a/Modules/expat/expat_external.h b/Modules/expat/expat_external.h --- a/Modules/expat/expat_external.h +++ b/Modules/expat/expat_external.h @@ -7,6 +7,10 @@ /* External API definitions */ +/* Namespace external symbols to allow multiple libexpat version to + co-exist. */ +#include "pyexpatns.h" + #if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__) #define XML_USE_MSC_EXTENSIONS 1 #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 16:12:28 2014 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 4 Feb 2014 16:12:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4zICgjMTkxODYp?= Message-ID: <3fJTsm2kkcz7LmH@mail.python.org> http://hg.python.org/cpython/rev/a2d877fb53f6 changeset: 88957:a2d877fb53f6 parent: 88955:1b8ba1346e67 parent: 88956:c242a8f30806 user: Benjamin Peterson date: Tue Feb 04 10:12:18 2014 -0500 summary: merge 3.3 (#19186) files: Misc/NEWS | 2 ++ Modules/expat/expat_external.h | 4 ++++ 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,8 @@ Library ------- +- Issue #19186: Restore namespacing of expat symbols inside the pyexpat module. + - Issue #20053: ensurepip (and hence venv) are no longer affected by the settings in the default pip configuration file. diff --git a/Modules/expat/expat_external.h b/Modules/expat/expat_external.h --- a/Modules/expat/expat_external.h +++ b/Modules/expat/expat_external.h @@ -7,6 +7,10 @@ /* External API definitions */ +/* Namespace external symbols to allow multiple libexpat version to + co-exist. */ +#include "pyexpatns.h" + #if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__) #define XML_USE_MSC_EXTENSIONS 1 #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 16:20:37 2014 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 4 Feb 2014 16:20:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_mmap_obmalloc_?= =?utf-8?q?arenas_so_that_they_may_be_immediately_returned_to_the_system?= Message-ID: <3fJV394WFnz7LpZ@mail.python.org> http://hg.python.org/cpython/rev/4e43e5b3f7fc changeset: 88958:4e43e5b3f7fc branch: 2.7 parent: 88943:aed29f86bfdc user: Benjamin Peterson date: Tue Feb 04 10:20:26 2014 -0500 summary: mmap obmalloc arenas so that they may be immediately returned to the system when unused (closes #20494) files: Misc/NEWS | 4 ++ Objects/obmalloc.c | 50 +++++++++++++++++++++++++-------- configure | 2 +- configure.ac | 2 +- pyconfig.h.in | 3 ++ 5 files changed, 46 insertions(+), 15 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,10 @@ Core and Builtins ----------------- +- Issue #20494: Ensure that free()d memory arenas are really released on POSIX + systems supporting anonymous memory mappings. Patch by Charles-Fran?ois + Natali. + - Issue #17825: Cursor "^" is correctly positioned for SyntaxError and IndentationError. diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -2,6 +2,13 @@ #ifdef WITH_PYMALLOC +#ifdef HAVE_MMAP + #include + #ifdef MAP_ANONYMOUS + #define ARENAS_USE_MMAP + #endif +#endif + #ifdef WITH_VALGRIND #include @@ -75,7 +82,8 @@ * Allocation strategy abstract: * * For small requests, the allocator sub-allocates blocks of memory. - * Requests greater than 256 bytes are routed to the system's allocator. + * Requests greater than SMALL_REQUEST_THRESHOLD bytes are routed to the + * system's allocator. * * Small requests are grouped in size classes spaced 8 bytes apart, due * to the required valid alignment of the returned address. Requests of @@ -107,10 +115,11 @@ * 57-64 64 7 * 65-72 72 8 * ... ... ... - * 241-248 248 30 - * 249-256 256 31 + * 497-504 504 62 + * 505-512 512 63 * - * 0, 257 and up: routed to the underlying allocator. + * 0, SMALL_REQUEST_THRESHOLD + 1 and up: routed to the underlying + * allocator. */ /*==========================================================================*/ @@ -143,10 +152,13 @@ * 1) ALIGNMENT <= SMALL_REQUEST_THRESHOLD <= 256 * 2) SMALL_REQUEST_THRESHOLD is evenly divisible by ALIGNMENT * + * Note: a size threshold of 512 guarantees that newly created dictionaries + * will be allocated from preallocated memory pools on 64-bit. + * * Although not required, for better performance and space efficiency, * it is recommended that SMALL_REQUEST_THRESHOLD is set to a power of 2. */ -#define SMALL_REQUEST_THRESHOLD 256 +#define SMALL_REQUEST_THRESHOLD 512 #define NB_SMALL_SIZE_CLASSES (SMALL_REQUEST_THRESHOLD / ALIGNMENT) /* @@ -174,15 +186,15 @@ /* * The allocator sub-allocates blocks of memory (called arenas) aligned * on a page boundary. This is a reserved virtual address space for the - * current process (obtained through a malloc call). In no way this means - * that the memory arenas will be used entirely. A malloc() is usually - * an address range reservation for bytes, unless all pages within this - * space are referenced subsequently. So malloc'ing big blocks and not using - * them does not mean "wasting memory". It's an addressable range wastage... + * current process (obtained through a malloc()/mmap() call). In no way this + * means that the memory arenas will be used entirely. A malloc() is + * usually an address range reservation for bytes, unless all pages within + * this space are referenced subsequently. So malloc'ing big blocks and not + * using them does not mean "wasting memory". It's an addressable range + * wastage... * - * Therefore, allocating arenas with malloc is not optimal, because there is - * some address space wastage, but this is the most portable way to request - * memory from the system across various platforms. + * Arenas are allocated with mmap() on systems supporting anonymous memory + * mappings to reduce heap fragmentation. */ #define ARENA_SIZE (256 << 10) /* 256KB */ @@ -440,6 +452,9 @@ , PT(48), PT(49), PT(50), PT(51), PT(52), PT(53), PT(54), PT(55) #if NB_SMALL_SIZE_CLASSES > 56 , PT(56), PT(57), PT(58), PT(59), PT(60), PT(61), PT(62), PT(63) +#if NB_SMALL_SIZE_CLASSES > 64 +#error "NB_SMALL_SIZE_CLASSES should be less than 64" +#endif /* NB_SMALL_SIZE_CLASSES > 64 */ #endif /* NB_SMALL_SIZE_CLASSES > 56 */ #endif /* NB_SMALL_SIZE_CLASSES > 48 */ #endif /* NB_SMALL_SIZE_CLASSES > 40 */ @@ -577,7 +592,12 @@ arenaobj = unused_arena_objects; unused_arena_objects = arenaobj->nextarena; assert(arenaobj->address == 0); +#ifdef ARENAS_USE_MMAP + arenaobj->address = (uptr)mmap(NULL, ARENA_SIZE, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +#else arenaobj->address = (uptr)malloc(ARENA_SIZE); +#endif if (arenaobj->address == 0) { /* The allocation failed: return NULL after putting the * arenaobj back. @@ -1054,7 +1074,11 @@ unused_arena_objects = ao; /* Free the entire arena. */ +#ifdef ARENAS_USE_MMAP + munmap((void *)ao->address, ARENA_SIZE); +#else free((void *)ao->address); +#endif ao->address = 0; /* mark unassociated */ --narenas_currently_allocated; diff --git a/configure b/configure --- a/configure +++ b/configure @@ -10164,7 +10164,7 @@ clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ - initgroups kill killpg lchmod lchown lstat mkfifo mknod mktime \ + initgroups kill killpg lchmod lchown lstat mkfifo mknod mktime mmap \ mremap nice pathconf pause plock poll pthread_init \ putenv readlink realpath \ select sem_open sem_timedwait sem_getvalue sem_unlink setegid seteuid \ diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -2905,7 +2905,7 @@ clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \ gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \ getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \ - initgroups kill killpg lchmod lchown lstat mkfifo mknod mktime \ + initgroups kill killpg lchmod lchown lstat mkfifo mknod mktime mmap \ mremap nice pathconf pause plock poll pthread_init \ putenv readlink realpath \ select sem_open sem_timedwait sem_getvalue sem_unlink setegid seteuid \ diff --git a/pyconfig.h.in b/pyconfig.h.in --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -475,6 +475,9 @@ /* Define to 1 if you have the `mktime' function. */ #undef HAVE_MKTIME +/* Define to 1 if you have the `mmap' function. */ +#undef HAVE_MMAP + /* Define to 1 if you have the `mremap' function. */ #undef HAVE_MREMAP -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 17:42:31 2014 From: python-checkins at python.org (vinay.sajip) Date: Tue, 4 Feb 2014 17:42:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTA5?= =?utf-8?q?=3A_Added_cross-reference_in_documentation=2E?= Message-ID: <3fJWsg3QMdz7Llf@mail.python.org> http://hg.python.org/cpython/rev/45aa817ec853 changeset: 88959:45aa817ec853 branch: 2.7 user: Vinay Sajip date: Tue Feb 04 16:25:41 2014 +0000 summary: Issue #20509: Added cross-reference in documentation. files: Doc/library/logging.config.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -81,8 +81,9 @@ .. function:: fileConfig(fname, defaults=None, disable_existing_loggers=True) Reads the logging configuration from a :mod:`configparser`\-format file - named *fname*. This function can be called several times from an - application, allowing an end user to select from various pre-canned + named *fname*. The format of the file should be as described in + :ref:`logging-config-fileformat`. This function can be called several times + from an application, allowing an end user to select from various pre-canned configurations (if the developer provides a mechanism to present the choices and load the chosen configuration). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 17:42:32 2014 From: python-checkins at python.org (vinay.sajip) Date: Tue, 4 Feb 2014 17:42:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTA5?= =?utf-8?q?=3A_Added_cross-reference_in_documentation=2E?= Message-ID: <3fJWsh5pv8z7LnV@mail.python.org> http://hg.python.org/cpython/rev/f8318b069146 changeset: 88960:f8318b069146 branch: 3.3 parent: 88956:c242a8f30806 user: Vinay Sajip date: Tue Feb 04 16:28:07 2014 +0000 summary: Issue #20509: Added cross-reference in documentation. files: Doc/library/logging.config.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -81,8 +81,9 @@ .. function:: fileConfig(fname, defaults=None, disable_existing_loggers=True) Reads the logging configuration from a :mod:`configparser`\-format file - named *fname*. This function can be called several times from an - application, allowing an end user to select from various pre-canned + named *fname*. The format of the file should be as described in + :ref:`logging-config-fileformat`. This function can be called several times + from an application, allowing an end user to select from various pre-canned configurations (if the developer provides a mechanism to present the choices and load the chosen configuration). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 17:42:34 2014 From: python-checkins at python.org (vinay.sajip) Date: Tue, 4 Feb 2014 17:42:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2320509=3A_Merged_documentation_update_from_3=2E?= =?utf-8?q?3=2E?= Message-ID: <3fJWsk1HqPz7Llr@mail.python.org> http://hg.python.org/cpython/rev/7d0a4f89c6ce changeset: 88961:7d0a4f89c6ce parent: 88957:a2d877fb53f6 parent: 88960:f8318b069146 user: Vinay Sajip date: Tue Feb 04 16:42:04 2014 +0000 summary: Closes #20509: Merged documentation update from 3.3. files: Doc/library/logging.config.rst | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -80,7 +80,9 @@ .. function:: fileConfig(fname, defaults=None, disable_existing_loggers=True) - Reads the logging configuration from a :mod:`configparser`\-format file. + Reads the logging configuration from a :mod:`configparser`\-format file. The + format of the file should be as described in + :ref:`logging-config-fileformat`. This function can be called several times from an application, allowing an end user to select from various pre-canned configurations (if the developer provides a mechanism to present the choices and load the chosen -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 18:18:41 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 4 Feb 2014 18:18:41 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_add_an_exam?= =?utf-8?q?ple_to_schedule_a_coroutine_from_a_different_thread?= Message-ID: <3fJXgP0twQz7LjW@mail.python.org> http://hg.python.org/cpython/rev/854d05c13a8e changeset: 88962:854d05c13a8e user: Victor Stinner date: Tue Feb 04 18:18:27 2014 +0100 summary: asyncio doc: add an example to schedule a coroutine from a different thread files: Doc/library/asyncio-dev.rst | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -13,12 +13,15 @@ ------------------------------ An event loop runs in a thread and executes all callbacks and tasks in the same -thread. If a callback should be scheduled from a different thread, the -:meth:`BaseEventLoop.call_soon_threadsafe` method should be used. +thread. While a task in 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 +and the event loop executes the next task. -While a task in 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 and the -event loop executes the next task. +To schedule a callback from a different thread, the +:meth:`BaseEventLoop.call_soon_threadsafe` method should be used. Example to +schedule a coroutine from a different:: + + loop.call_soon_threadsafe(asyncio.async, coro_func()) To handle signals and to execute subprocesses, the event loop must be run in the main thread. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 18:37:53 2014 From: python-checkins at python.org (zach.ware) Date: Tue, 4 Feb 2014 18:37:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Correct_and_future-proof_?= =?utf-8?q?PC_and_PCbuild_directory_descriptions=2E?= Message-ID: <3fJY5Y5RxQz7LjV@mail.python.org> http://hg.python.org/devguide/rev/6fb9db43a372 changeset: 664:6fb9db43a372 user: Zachary Ware date: Tue Feb 04 11:37:23 2014 -0600 summary: Correct and future-proof PC and PCbuild directory descriptions. files: setup.rst | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/setup.rst b/setup.rst --- a/setup.rst +++ b/setup.rst @@ -315,11 +315,12 @@ Code for all built-in types. ``PC`` - Windows-specific code along with build files for VC 6, 7, & 8 along with - OS/2. + Windows-specific code along with legacy build files for previously used + versions of MSVC. ``PCbuild`` - Build files for VC 9 and newer. + Build files for the version of MSVC currently used for the Windows + installers provided on python.org. ``Parser`` Code related to the parser. The definition of the AST nodes is also kept -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Tue Feb 4 22:49:44 2014 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 4 Feb 2014 22:49:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_missing_word_=28=22thr?= =?utf-8?q?ead=22=29_to_sentence_about_call=5Fsoon=5Fthreadsafe=2E?= Message-ID: <3fJfh80dFgz7LjS@mail.python.org> http://hg.python.org/cpython/rev/e0bcafbffe7e changeset: 88963:e0bcafbffe7e user: Guido van Rossum date: Tue Feb 04 13:49:34 2014 -0800 summary: Add missing word ("thread") to sentence about call_soon_threadsafe. files: Doc/library/asyncio-dev.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -19,7 +19,7 @@ To schedule a callback from a different thread, the :meth:`BaseEventLoop.call_soon_threadsafe` method should be used. Example to -schedule a coroutine from a different:: +schedule a coroutine from a different thread:: loop.call_soon_threadsafe(asyncio.async, coro_func()) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 4 23:27:24 2014 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 4 Feb 2014 23:27:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Cosmetic_improv?= =?utf-8?q?ement_to_test=5F=5Frun=5Fonce=5Flogging=28=29_mock_argument=2E?= Message-ID: <3fJgWc2SG6z7LjR@mail.python.org> http://hg.python.org/cpython/rev/92fc6850dea0 changeset: 88964:92fc6850dea0 user: Guido van Rossum date: Tue Feb 04 14:27:14 2014 -0800 summary: asyncio: Cosmetic improvement to test__run_once_logging() mock argument. files: Lib/test/test_asyncio/test_base_events.py | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -190,7 +190,7 @@ @unittest.mock.patch('asyncio.base_events.time') @unittest.mock.patch('asyncio.base_events.logger') - def test__run_once_logging(self, m_logging, m_time): + def test__run_once_logging(self, m_logger, m_time): # Log to INFO level if timeout > 1.0 sec. idx = -1 data = [10.0, 10.0, 12.0, 13.0] @@ -201,20 +201,18 @@ return data[idx] m_time.monotonic = monotonic - m_logging.INFO = logging.INFO - m_logging.DEBUG = logging.DEBUG self.loop._scheduled.append( asyncio.TimerHandle(11.0, lambda: True, ())) self.loop._process_events = unittest.mock.Mock() self.loop._run_once() - self.assertEqual(logging.INFO, m_logging.log.call_args[0][0]) + self.assertEqual(logging.INFO, m_logger.log.call_args[0][0]) idx = -1 data = [10.0, 10.0, 10.3, 13.0] self.loop._scheduled = [asyncio.TimerHandle(11.0, lambda:True, ())] self.loop._run_once() - self.assertEqual(logging.DEBUG, m_logging.log.call_args[0][0]) + self.assertEqual(logging.DEBUG, m_logger.log.call_args[0][0]) def test__run_once_schedule_handle(self): handle = None -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 00:31:44 2014 From: python-checkins at python.org (christian.heimes) Date: Wed, 5 Feb 2014 00:31:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTE1?= =?utf-8?q?=3A_Fix_NULL_pointer_dereference_introduced_by_issue_=2320368?= Message-ID: <3fJhxr1Jrsz7Lk4@mail.python.org> http://hg.python.org/cpython/rev/d83ce3a2d954 changeset: 88965:d83ce3a2d954 branch: 3.3 parent: 88960:f8318b069146 user: Christian Heimes date: Wed Feb 05 00:29:17 2014 +0100 summary: Issue #20515: Fix NULL pointer dereference introduced by issue #20368 CID 1167595 files: Misc/NEWS | 2 ++ Modules/_tkinter.c | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,8 @@ Library ------- +- Issue #20515: Fix NULL pointer dereference introduced by issue #20368. + - Issue #19186: Restore namespacing of expat symbols inside the pyexpat module. - Issue #20426: When passing the re.DEBUG flag, re.compile() displays the diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -1568,6 +1568,9 @@ if (PyUnicode_Check(in)) { Py_ssize_t size; s = PyUnicode_AsUTF8AndSize(in, &size); + if (s == NULL) { + return 0; + } if (size > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "string is too long"); return 0; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 00:31:45 2014 From: python-checkins at python.org (christian.heimes) Date: Wed, 5 Feb 2014 00:31:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320515=3A_Fix_NULL_pointer_dereference_introduce?= =?utf-8?q?d_by_issue_=2320368?= Message-ID: <3fJhxs3vyjz7Lkb@mail.python.org> http://hg.python.org/cpython/rev/145032f626d3 changeset: 88966:145032f626d3 parent: 88964:92fc6850dea0 parent: 88965:d83ce3a2d954 user: Christian Heimes date: Wed Feb 05 00:29:48 2014 +0100 summary: Issue #20515: Fix NULL pointer dereference introduced by issue #20368 CID 1167595 files: Misc/NEWS | 2 ++ Modules/_tkinter.c | 3 +++ 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,8 @@ Library ------- +- Issue #20515: Fix NULL pointer dereference introduced by issue #20368. + - Issue #19186: Restore namespacing of expat symbols inside the pyexpat module. - Issue #20053: ensurepip (and hence venv) are no longer affected by the diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -1397,6 +1397,9 @@ if (PyUnicode_Check(in)) { Py_ssize_t size; s = PyUnicode_AsUTF8AndSize(in, &size); + if (s == NULL) { + return 0; + } if (size > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "string is too long"); return 0; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 03:45:08 2014 From: python-checkins at python.org (ned.deily) Date: Wed, 5 Feb 2014 03:45:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320465=3A_Update_S?= =?utf-8?q?QLite_shipped_with_OS_X_installer_to_3=2E8=2E3=2E?= Message-ID: <3fJnF02WFrz7LjS@mail.python.org> http://hg.python.org/cpython/rev/32af4954e46a changeset: 88967:32af4954e46a user: Ned Deily date: Tue Feb 04 18:44:17 2014 -0800 summary: Issue #20465: Update SQLite shipped with OS X installer to 3.8.3. files: Mac/BuildScript/build-installer.py | 6 +++--- Misc/NEWS | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -283,9 +283,9 @@ ), ), dict( - name="SQLite 3.8.1", - url="http://www.sqlite.org/2013/sqlite-autoconf-3080100.tar.gz", - checksum='8b5a0a02dfcb0c7daf90856a5cfd485a', + name="SQLite 3.8.3", + url="http://www.sqlite.org/2014/sqlite-autoconf-3080300.tar.gz", + checksum='11572878dc0ac74ae370367a464ab5cf', extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS4 ' '-DSQLITE_ENABLE_FTS3_PARENTHESIS ' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -149,6 +149,11 @@ input and output sections of the block, allowing external tools to verify that the input has not changed (and thus the output is not out-of-date). +Build +----- + +- Issue #20465: Update SQLite shipped with OS X installer to 3.8.3. + What's New in Python 3.4.0 Beta 3? ================================== -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Wed Feb 5 09:44:32 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 05 Feb 2014 09:44:32 +0100 Subject: [Python-checkins] Daily reference leaks (145032f626d3): sum=-7 Message-ID: results for 145032f626d3 on branch "default" -------------------------------------------- test_site leaked [2, -2, 2] references, sum=2 test_site leaked [2, -2, 2] memory blocks, sum=2 test_urllib2net leaked [0, 1591, -1602] references, sum=-11 test_urllib2net leaked [0, 1410, -1410] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogYMmhlB', '-x'] From python-checkins at python.org Wed Feb 5 12:43:06 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 5 Feb 2014 12:43:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320489=3A_Explicit?= =?utf-8?q?ly_qualified_expressions_for_default_values_in_methods=2E?= Message-ID: <3fK19k12P7z7LjS@mail.python.org> http://hg.python.org/cpython/rev/31ddd45a05ba changeset: 88968:31ddd45a05ba user: Serhiy Storchaka date: Wed Feb 05 13:34:01 2014 +0200 summary: Issue #20489: Explicitly qualified expressions for default values in methods. files: Modules/clinic/zlibmodule.c.h | 6 +++--- Modules/zlibmodule.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -245,7 +245,7 @@ } PyDoc_STRVAR(zlib_Compress_flush__doc__, -"sig=($self, mode=Z_FINISH)\n" +"sig=($self, mode=zlib.Z_FINISH)\n" "Return a bytes object containing any remaining compressed data.\n" "\n" " mode\n" @@ -325,7 +325,7 @@ #endif /* !defined(ZLIB_DECOMPRESS_COPY_METHODDEF) */ PyDoc_STRVAR(zlib_Decompress_flush__doc__, -"sig=($self, length=DEF_BUF_SIZE)\n" +"sig=($self, length=zlib.DEF_BUF_SIZE)\n" "Return a bytes object containing any remaining decompressed data.\n" "\n" " length\n" @@ -424,4 +424,4 @@ return return_value; } -/*[clinic end generated code: output=21556008559f839c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=67d3e81eafcfb982 input=a9049054013a1b77]*/ diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -828,7 +828,7 @@ /*[clinic input] zlib.Compress.flush - mode: int(c_default="Z_FINISH") = Z_FINISH + mode: int(c_default="Z_FINISH") = zlib.Z_FINISH One of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH. If mode == Z_FINISH, the compressor object can no longer be used after calling the flush() method. Otherwise, more data @@ -840,7 +840,7 @@ static PyObject * zlib_Compress_flush_impl(compobject *self, int mode) -/*[clinic end generated code: output=a203f4cefc9de727 input=6982996afe0772d8]*/ +/*[clinic end generated code: output=a203f4cefc9de727 input=73ed066794bd15bc]*/ { int err; unsigned int length = DEF_BUF_SIZE, new_length; @@ -1046,7 +1046,7 @@ /*[clinic input] zlib.Decompress.flush - length: uint(c_default="DEF_BUF_SIZE") = DEF_BUF_SIZE + length: uint(c_default="DEF_BUF_SIZE") = zlib.DEF_BUF_SIZE the initial size of the output buffer. / @@ -1055,7 +1055,7 @@ static PyObject * zlib_Decompress_flush_impl(compobject *self, unsigned int length) -/*[clinic end generated code: output=db6fb753ab698e22 input=fe7954136712c353]*/ +/*[clinic end generated code: output=db6fb753ab698e22 input=1580956505978993]*/ { int err; unsigned int new_length; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 12:43:07 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 5 Feb 2014 12:43:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNDk4?= =?utf-8?q?=3A_Fixed_io=2EStringIO_tests_for_newline=3D=27=5Cn=27=2E_Added?= =?utf-8?q?_new_tests=2E?= Message-ID: <3fK19l3fWbz7Ljc@mail.python.org> http://hg.python.org/cpython/rev/07e7bb29a2c5 changeset: 88969:07e7bb29a2c5 branch: 2.7 parent: 88959:45aa817ec853 user: Serhiy Storchaka date: Wed Feb 05 13:41:38 2014 +0200 summary: Issue #20498: Fixed io.StringIO tests for newline='\n'. Added new tests. files: Lib/test/test_memoryio.py | 37 ++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -522,6 +522,17 @@ self.assertIsNone(memio.errors) self.assertFalse(memio.line_buffering) + def test_newline_default(self): + memio = self.ioclass("a\nb\r\nc\rd") + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + + memio = self.ioclass() + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + def test_newline_none(self): # newline=None memio = self.ioclass("a\nb\r\nc\rd", newline=None) @@ -531,6 +542,8 @@ self.assertEqual(memio.read(2), "\nb") self.assertEqual(memio.read(2), "\nc") self.assertEqual(memio.read(1), "\n") + self.assertEqual(memio.getvalue(), "a\nb\nc\nd") + memio = self.ioclass(newline=None) self.assertEqual(2, memio.write("a\n")) self.assertEqual(3, memio.write("b\r\n")) @@ -538,6 +551,7 @@ memio.seek(0) self.assertEqual(memio.read(), "a\nb\nc\nd") self.assertEqual(memio.getvalue(), "a\nb\nc\nd") + memio = self.ioclass("a\r\nb", newline=None) self.assertEqual(memio.read(3), "a\nb") @@ -550,6 +564,7 @@ self.assertEqual(memio.read(2), "\nc") self.assertEqual(memio.read(1), "\r") self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + memio = self.ioclass(newline="") self.assertEqual(2, memio.write("a\n")) self.assertEqual(2, memio.write("b\r")) @@ -557,11 +572,19 @@ self.assertEqual(2, memio.write("\rd")) memio.seek(0) self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") def test_newline_lf(self): # newline="\n" - memio = self.ioclass("a\nb\r\nc\rd") + memio = self.ioclass("a\nb\r\nc\rd", newline="\n") self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + + memio = self.ioclass(newline="\n") + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") def test_newline_cr(self): # newline="\r" @@ -569,6 +592,12 @@ self.assertEqual(memio.read(), "a\rb\r\rc\rd") memio.seek(0) self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"]) + self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd") + + memio = self.ioclass(newline="\r") + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"]) memio.seek(0) self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"]) self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd") @@ -583,6 +612,12 @@ self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"]) self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd") + memio = self.ioclass(newline="\r\n") + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd") + def test_issue5265(self): # StringIO can duplicate newlines in universal newlines mode memio = self.ioclass("a\r\nb\r\n", newline=None) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 12:43:08 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 5 Feb 2014 12:43:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNDk4?= =?utf-8?q?=3A_Fixed_io=2EStringIO_tests_for_newline=3D=27=5Cn=27=2E_Added?= =?utf-8?q?_new_tests=2E?= Message-ID: <3fK19m6B69z7Lk3@mail.python.org> http://hg.python.org/cpython/rev/e23c928b9e39 changeset: 88970:e23c928b9e39 branch: 3.3 parent: 88965:d83ce3a2d954 user: Serhiy Storchaka date: Wed Feb 05 13:42:01 2014 +0200 summary: Issue #20498: Fixed io.StringIO tests for newline='\n'. Added new tests. files: Lib/test/test_memoryio.py | 37 ++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -536,6 +536,17 @@ self.assertIsNone(memio.errors) self.assertFalse(memio.line_buffering) + def test_newline_default(self): + memio = self.ioclass("a\nb\r\nc\rd") + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + + memio = self.ioclass() + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + def test_newline_none(self): # newline=None memio = self.ioclass("a\nb\r\nc\rd", newline=None) @@ -545,6 +556,8 @@ self.assertEqual(memio.read(2), "\nb") self.assertEqual(memio.read(2), "\nc") self.assertEqual(memio.read(1), "\n") + self.assertEqual(memio.getvalue(), "a\nb\nc\nd") + memio = self.ioclass(newline=None) self.assertEqual(2, memio.write("a\n")) self.assertEqual(3, memio.write("b\r\n")) @@ -552,6 +565,7 @@ memio.seek(0) self.assertEqual(memio.read(), "a\nb\nc\nd") self.assertEqual(memio.getvalue(), "a\nb\nc\nd") + memio = self.ioclass("a\r\nb", newline=None) self.assertEqual(memio.read(3), "a\nb") @@ -564,6 +578,7 @@ self.assertEqual(memio.read(2), "\nc") self.assertEqual(memio.read(1), "\r") self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + memio = self.ioclass(newline="") self.assertEqual(2, memio.write("a\n")) self.assertEqual(2, memio.write("b\r")) @@ -571,11 +586,19 @@ self.assertEqual(2, memio.write("\rd")) memio.seek(0) self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") def test_newline_lf(self): # newline="\n" - memio = self.ioclass("a\nb\r\nc\rd") + memio = self.ioclass("a\nb\r\nc\rd", newline="\n") self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + + memio = self.ioclass(newline="\n") + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") def test_newline_cr(self): # newline="\r" @@ -583,6 +606,12 @@ self.assertEqual(memio.read(), "a\rb\r\rc\rd") memio.seek(0) self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"]) + self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd") + + memio = self.ioclass(newline="\r") + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"]) memio.seek(0) self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"]) self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd") @@ -597,6 +626,12 @@ self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"]) self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd") + memio = self.ioclass(newline="\r\n") + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd") + def test_issue5265(self): # StringIO can duplicate newlines in universal newlines mode memio = self.ioclass("a\r\nb\r\n", newline=None) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 12:43:10 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 5 Feb 2014 12:43:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320498=3A_Fixed_io=2EStringIO_tests_for_newline?= =?utf-8?b?PSdcbicuIEFkZGVkIG5ldyB0ZXN0cy4=?= Message-ID: <3fK19p1xnYz7LkH@mail.python.org> http://hg.python.org/cpython/rev/7ed8a9f9831d changeset: 88971:7ed8a9f9831d parent: 88968:31ddd45a05ba parent: 88970:e23c928b9e39 user: Serhiy Storchaka date: Wed Feb 05 13:42:29 2014 +0200 summary: Issue #20498: Fixed io.StringIO tests for newline='\n'. Added new tests. files: Lib/test/test_memoryio.py | 37 ++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -536,6 +536,17 @@ self.assertIsNone(memio.errors) self.assertFalse(memio.line_buffering) + def test_newline_default(self): + memio = self.ioclass("a\nb\r\nc\rd") + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + + memio = self.ioclass() + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + def test_newline_none(self): # newline=None memio = self.ioclass("a\nb\r\nc\rd", newline=None) @@ -545,6 +556,8 @@ self.assertEqual(memio.read(2), "\nb") self.assertEqual(memio.read(2), "\nc") self.assertEqual(memio.read(1), "\n") + self.assertEqual(memio.getvalue(), "a\nb\nc\nd") + memio = self.ioclass(newline=None) self.assertEqual(2, memio.write("a\n")) self.assertEqual(3, memio.write("b\r\n")) @@ -552,6 +565,7 @@ memio.seek(0) self.assertEqual(memio.read(), "a\nb\nc\nd") self.assertEqual(memio.getvalue(), "a\nb\nc\nd") + memio = self.ioclass("a\r\nb", newline=None) self.assertEqual(memio.read(3), "a\nb") @@ -564,6 +578,7 @@ self.assertEqual(memio.read(2), "\nc") self.assertEqual(memio.read(1), "\r") self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + memio = self.ioclass(newline="") self.assertEqual(2, memio.write("a\n")) self.assertEqual(2, memio.write("b\r")) @@ -571,11 +586,19 @@ self.assertEqual(2, memio.write("\rd")) memio.seek(0) self.assertEqual(list(memio), ["a\n", "b\r\n", "c\r", "d"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") def test_newline_lf(self): # newline="\n" - memio = self.ioclass("a\nb\r\nc\rd") + memio = self.ioclass("a\nb\r\nc\rd", newline="\n") self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") + + memio = self.ioclass(newline="\n") + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\n", "b\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\nb\r\nc\rd") def test_newline_cr(self): # newline="\r" @@ -583,6 +606,12 @@ self.assertEqual(memio.read(), "a\rb\r\rc\rd") memio.seek(0) self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"]) + self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd") + + memio = self.ioclass(newline="\r") + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\r", "b\r", "\r", "c\r", "d"]) memio.seek(0) self.assertEqual(memio.readlines(), ["a\r", "b\r", "\r", "c\r", "d"]) self.assertEqual(memio.getvalue(), "a\rb\r\rc\rd") @@ -597,6 +626,12 @@ self.assertEqual(memio.readlines(), ["a\r\n", "b\r\r\n", "c\rd"]) self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd") + memio = self.ioclass(newline="\r\n") + self.assertEqual(memio.write("a\nb\r\nc\rd"), 8) + memio.seek(0) + self.assertEqual(list(memio), ["a\r\n", "b\r\r\n", "c\rd"]) + self.assertEqual(memio.getvalue(), "a\r\nb\r\r\nc\rd") + def test_issue5265(self): # StringIO can duplicate newlines in universal newlines mode memio = self.ioclass("a\r\nb\r\n", newline=None) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 14:55:12 2014 From: python-checkins at python.org (nick.coghlan) Date: Wed, 5 Feb 2014 14:55:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320053=3A_new_test?= =?utf-8?q?_to_check_an_assumption?= Message-ID: <3fK4685hmxz7Llm@mail.python.org> http://hg.python.org/cpython/rev/ddc82c4d1a44 changeset: 88972:ddc82c4d1a44 user: Nick Coghlan date: Wed Feb 05 23:54:55 2014 +1000 summary: Issue #20053: new test to check an assumption files: Lib/test/test_venv.py | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -288,6 +288,13 @@ self.run_with_capture(venv.create, self.env_dir, with_pip=False) self.assert_pip_not_installed() + def test_devnull_exists_and_is_empty(self): + # Fix for issue #20053 uses os.devnull to force a config file to + # appear empty. Make sure that assumption is valid cross platform. + self.assertTrue(os.path.exists, os.devnull) + with open(os.devnull, "rb") as f: + self.assertEqual(f.read(), b"") + # Requesting pip fails without SSL (http://bugs.python.org/issue19744) @unittest.skipIf(ssl is None, ensurepip._MISSING_SSL_MESSAGE) def test_with_pip(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 16:33:24 2014 From: python-checkins at python.org (eric.smith) Date: Wed, 5 Feb 2014 16:33:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_TestNamedTuple=2Etest=5Fpi?= =?utf-8?q?ckle_was_only_testing_through_protocol_2=2E_Changed_to_have?= Message-ID: <3fK6HS0qf0z7LjP@mail.python.org> http://hg.python.org/cpython/rev/3dcbf8f928ec changeset: 88973:3dcbf8f928ec user: Eric V. Smith date: Wed Feb 05 10:33:14 2014 -0500 summary: TestNamedTuple.test_pickle was only testing through protocol 2. Changed to have it automatically test through the most recent version. files: Lib/test/test_collections.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -301,7 +301,7 @@ for module in (pickle,): loads = getattr(module, 'loads') dumps = getattr(module, 'dumps') - for protocol in -1, 0, 1, 2: + for protocol in range(-1, module.HIGHEST_PROTOCOL + 1): q = loads(dumps(p, protocol)) self.assertEqual(p, q) self.assertEqual(p._fields, q._fields) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 19:55:29 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 5 Feb 2014 19:55:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE5OTIw?= =?utf-8?q?=3A_TarFile=2Elist=28=29_no_longer_fails_when_outputs_a_listing?= Message-ID: <3fKBmd2WSnz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/a5895fca91f3 changeset: 88974:a5895fca91f3 branch: 3.3 parent: 88970:e23c928b9e39 user: Serhiy Storchaka date: Wed Feb 05 20:53:36 2014 +0200 summary: Issue #19920: TarFile.list() no longer fails when outputs a listing containing non-encodable characters. Added tests for TarFile.list(). Based on patch by Vajrasky Kok. files: Lib/tarfile.py | 28 ++++++--- Lib/test/test_tarfile.py | 78 ++++++++++++++++++++++++++++ Misc/NEWS | 5 + 3 files changed, 100 insertions(+), 11 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -281,6 +281,12 @@ DeprecationWarning, 2) return stat.filemode(mode) +def _safe_print(s): + encoding = getattr(sys.stdout, 'encoding', None) + if encoding is not None: + s = s.encode(encoding, 'backslashreplace').decode(encoding) + print(s, end=' ') + class TarError(Exception): """Base exception.""" @@ -1870,24 +1876,24 @@ for tarinfo in self: if verbose: - print(stat.filemode(tarinfo.mode), end=' ') - print("%s/%s" % (tarinfo.uname or tarinfo.uid, - tarinfo.gname or tarinfo.gid), end=' ') + _safe_print(stat.filemode(tarinfo.mode)) + _safe_print("%s/%s" % (tarinfo.uname or tarinfo.uid, + tarinfo.gname or tarinfo.gid)) if tarinfo.ischr() or tarinfo.isblk(): - print("%10s" % ("%d,%d" \ - % (tarinfo.devmajor, tarinfo.devminor)), end=' ') + _safe_print("%10s" % + ("%d,%d" % (tarinfo.devmajor, tarinfo.devminor))) else: - print("%10d" % tarinfo.size, end=' ') - print("%d-%02d-%02d %02d:%02d:%02d" \ - % time.localtime(tarinfo.mtime)[:6], end=' ') + _safe_print("%10d" % tarinfo.size) + _safe_print("%d-%02d-%02d %02d:%02d:%02d" \ + % time.localtime(tarinfo.mtime)[:6]) - print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') + _safe_print(tarinfo.name + ("/" if tarinfo.isdir() else "")) if verbose: if tarinfo.issym(): - print("->", tarinfo.linkname, end=' ') + _safe_print("-> " + tarinfo.linkname) if tarinfo.islnk(): - print("link to", tarinfo.linkname, end=' ') + _safe_print("link to " + tarinfo.linkname) print() def add(self, name, arcname=None, recursive=True, exclude=None, *, filter=None): diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -217,6 +217,84 @@ pass +class ListTest(ReadTest, unittest.TestCase): + + # Override setUp to use default encoding (UTF-8) + def setUp(self): + self.tar = tarfile.open(self.tarname, mode=self.mode) + + def test_list(self): + tio = io.TextIOWrapper(io.BytesIO(), 'ascii', newline='\n') + with support.swap_attr(sys, 'stdout', tio): + self.tar.list(verbose=False) + out = tio.detach().getvalue() + self.assertIn(b'ustar/conttype', out) + self.assertIn(b'ustar/regtype', out) + self.assertIn(b'ustar/lnktype', out) + self.assertIn(b'ustar' + (b'/12345' * 40) + b'67/longname', out) + self.assertIn(b'./ustar/linktest2/symtype', out) + self.assertIn(b'./ustar/linktest2/lnktype', out) + # Make sure it puts trailing slash for directory + self.assertIn(b'ustar/dirtype/', out) + self.assertIn(b'ustar/dirtype-with-size/', out) + # Make sure it is able to print unencodable characters + self.assertIn(br'ustar/umlauts-' + br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) + self.assertIn(br'misc/regtype-hpux-signed-chksum-' + br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) + self.assertIn(br'misc/regtype-old-v7-signed-chksum-' + br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) + self.assertIn(br'pax/bad-pax-\udce4\udcf6\udcfc', out) + self.assertIn(br'pax/hdrcharset-\udce4\udcf6\udcfc', out) + # Make sure it prints files separated by one newline without any + # 'ls -l'-like accessories if verbose flag is not being used + # ... + # ustar/conttype + # ustar/regtype + # ... + self.assertRegex(out, br'ustar/conttype ?\r?\n' + br'ustar/regtype ?\r?\n') + # Make sure it does not print the source of link without verbose flag + self.assertNotIn(b'link to', out) + self.assertNotIn(b'->', out) + + def test_list_verbose(self): + tio = io.TextIOWrapper(io.BytesIO(), 'ascii', newline='\n') + with support.swap_attr(sys, 'stdout', tio): + self.tar.list(verbose=True) + out = tio.detach().getvalue() + # Make sure it prints files separated by one newline with 'ls -l'-like + # accessories if verbose flag is being used + # ... + # ?rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/conttype + # ?rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/regtype + # ... + self.assertRegex(out, (br'-rw-r--r-- tarfile/tarfile\s+7011 ' + br'\d{4}-\d\d-\d\d\s+\d\d:\d\d:\d\d ' + br'ustar/\w+type ?\r?\n') * 2) + # Make sure it prints the source of link with verbose flag + self.assertIn(b'ustar/symtype -> regtype', out) + self.assertIn(b'./ustar/linktest2/symtype -> ../linktest1/regtype', out) + self.assertIn(b'./ustar/linktest2/lnktype link to ' + b'./ustar/linktest1/regtype', out) + self.assertIn(b'gnu' + (b'/123' * 125) + b'/longlink link to gnu' + + (b'/123' * 125) + b'/longname', out) + self.assertIn(b'pax' + (b'/123' * 125) + b'/longlink link to pax' + + (b'/123' * 125) + b'/longname', out) + + +class GzipListTest(GzipTest, ListTest): + pass + + +class Bz2ListTest(Bz2Test, ListTest): + pass + + +class LzmaListTest(LzmaTest, ListTest): + pass + + class CommonReadTest(ReadTest): def test_empty_tarfile(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,9 @@ Library ------- +- Issue #19920: TarFile.list() no longer fails when outputs a listing + containing non-encodable characters. Based on patch by Vajrasky Kok. + - Issue #20515: Fix NULL pointer dereference introduced by issue #20368. - Issue #19186: Restore namespacing of expat symbols inside the pyexpat module. @@ -321,6 +324,8 @@ Tests ----- +- Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. + - Issue #19990: Added tests for the imghdr module. Based on patch by Claudiu Popa. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 19:55:30 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 5 Feb 2014 19:55:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2319920=3A_TarFile=2Elist=28=29_no_longer_fails_w?= =?utf-8?q?hen_outputs_a_listing?= Message-ID: <3fKBmf6PVcz7Lk9@mail.python.org> http://hg.python.org/cpython/rev/077aa6d4f3b7 changeset: 88975:077aa6d4f3b7 parent: 88973:3dcbf8f928ec parent: 88974:a5895fca91f3 user: Serhiy Storchaka date: Wed Feb 05 20:54:43 2014 +0200 summary: Issue #19920: TarFile.list() no longer fails when outputs a listing containing non-encodable characters. Added tests for TarFile.list(). Based on patch by Vajrasky Kok. files: Lib/tarfile.py | 28 +++-- Lib/test/test_tarfile.py | 117 ++++++++++++++++++++++---- Misc/NEWS | 5 + 3 files changed, 121 insertions(+), 29 deletions(-) diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -257,6 +257,12 @@ DeprecationWarning, 2) return stat.filemode(mode) +def _safe_print(s): + encoding = getattr(sys.stdout, 'encoding', None) + if encoding is not None: + s = s.encode(encoding, 'backslashreplace').decode(encoding) + print(s, end=' ') + class TarError(Exception): """Base exception.""" @@ -1846,24 +1852,24 @@ for tarinfo in self: if verbose: - print(stat.filemode(tarinfo.mode), end=' ') - print("%s/%s" % (tarinfo.uname or tarinfo.uid, - tarinfo.gname or tarinfo.gid), end=' ') + _safe_print(stat.filemode(tarinfo.mode)) + _safe_print("%s/%s" % (tarinfo.uname or tarinfo.uid, + tarinfo.gname or tarinfo.gid)) if tarinfo.ischr() or tarinfo.isblk(): - print("%10s" % ("%d,%d" \ - % (tarinfo.devmajor, tarinfo.devminor)), end=' ') + _safe_print("%10s" % + ("%d,%d" % (tarinfo.devmajor, tarinfo.devminor))) else: - print("%10d" % tarinfo.size, end=' ') - print("%d-%02d-%02d %02d:%02d:%02d" \ - % time.localtime(tarinfo.mtime)[:6], end=' ') + _safe_print("%10d" % tarinfo.size) + _safe_print("%d-%02d-%02d %02d:%02d:%02d" \ + % time.localtime(tarinfo.mtime)[:6]) - print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') + _safe_print(tarinfo.name + ("/" if tarinfo.isdir() else "")) if verbose: if tarinfo.issym(): - print("->", tarinfo.linkname, end=' ') + _safe_print("-> " + tarinfo.linkname) if tarinfo.islnk(): - print("link to", tarinfo.linkname, end=' ') + _safe_print("link to " + tarinfo.linkname) print() def add(self, name, arcname=None, recursive=True, exclude=None, *, filter=None): diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -219,6 +219,84 @@ pass +class ListTest(ReadTest, unittest.TestCase): + + # Override setUp to use default encoding (UTF-8) + def setUp(self): + self.tar = tarfile.open(self.tarname, mode=self.mode) + + def test_list(self): + tio = io.TextIOWrapper(io.BytesIO(), 'ascii', newline='\n') + with support.swap_attr(sys, 'stdout', tio): + self.tar.list(verbose=False) + out = tio.detach().getvalue() + self.assertIn(b'ustar/conttype', out) + self.assertIn(b'ustar/regtype', out) + self.assertIn(b'ustar/lnktype', out) + self.assertIn(b'ustar' + (b'/12345' * 40) + b'67/longname', out) + self.assertIn(b'./ustar/linktest2/symtype', out) + self.assertIn(b'./ustar/linktest2/lnktype', out) + # Make sure it puts trailing slash for directory + self.assertIn(b'ustar/dirtype/', out) + self.assertIn(b'ustar/dirtype-with-size/', out) + # Make sure it is able to print unencodable characters + self.assertIn(br'ustar/umlauts-' + br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) + self.assertIn(br'misc/regtype-hpux-signed-chksum-' + br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) + self.assertIn(br'misc/regtype-old-v7-signed-chksum-' + br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) + self.assertIn(br'pax/bad-pax-\udce4\udcf6\udcfc', out) + self.assertIn(br'pax/hdrcharset-\udce4\udcf6\udcfc', out) + # Make sure it prints files separated by one newline without any + # 'ls -l'-like accessories if verbose flag is not being used + # ... + # ustar/conttype + # ustar/regtype + # ... + self.assertRegex(out, br'ustar/conttype ?\r?\n' + br'ustar/regtype ?\r?\n') + # Make sure it does not print the source of link without verbose flag + self.assertNotIn(b'link to', out) + self.assertNotIn(b'->', out) + + def test_list_verbose(self): + tio = io.TextIOWrapper(io.BytesIO(), 'ascii', newline='\n') + with support.swap_attr(sys, 'stdout', tio): + self.tar.list(verbose=True) + out = tio.detach().getvalue() + # Make sure it prints files separated by one newline with 'ls -l'-like + # accessories if verbose flag is being used + # ... + # ?rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/conttype + # ?rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/regtype + # ... + self.assertRegex(out, (br'\?rw-r--r-- tarfile/tarfile\s+7011 ' + br'\d{4}-\d\d-\d\d\s+\d\d:\d\d:\d\d ' + br'ustar/\w+type ?\r?\n') * 2) + # Make sure it prints the source of link with verbose flag + self.assertIn(b'ustar/symtype -> regtype', out) + self.assertIn(b'./ustar/linktest2/symtype -> ../linktest1/regtype', out) + self.assertIn(b'./ustar/linktest2/lnktype link to ' + b'./ustar/linktest1/regtype', out) + self.assertIn(b'gnu' + (b'/123' * 125) + b'/longlink link to gnu' + + (b'/123' * 125) + b'/longname', out) + self.assertIn(b'pax' + (b'/123' * 125) + b'/longlink link to pax' + + (b'/123' * 125) + b'/longname', out) + + +class GzipListTest(GzipTest, ListTest): + pass + + +class Bz2ListTest(Bz2Test, ListTest): + pass + + +class LzmaListTest(LzmaTest, ListTest): + pass + + class CommonReadTest(ReadTest): def test_empty_tarfile(self): @@ -1766,8 +1844,9 @@ class CommandLineTest(unittest.TestCase): - def tarfilecmd(self, *args): - rc, out, err = script_helper.assert_python_ok('-m', 'tarfile', *args) + def tarfilecmd(self, *args, **kwargs): + rc, out, err = script_helper.assert_python_ok('-m', 'tarfile', *args, + **kwargs) return out.replace(os.linesep.encode(), b'\n') def tarfilecmd_failure(self, *args): @@ -1815,24 +1894,26 @@ support.unlink(tmpname) def test_list_command(self): - self.make_simple_tarfile(tmpname) - with support.captured_stdout() as t: - with tarfile.open(tmpname, 'r') as tf: - tf.list(verbose=False) - expected = t.getvalue().encode(sys.getfilesystemencoding()) - for opt in '-l', '--list': - out = self.tarfilecmd(opt, tmpname) - self.assertEqual(out, expected) + for tar_name in testtarnames: + with support.captured_stdout() as t: + with tarfile.open(tar_name, 'r') as tf: + tf.list(verbose=False) + expected = t.getvalue().encode('ascii', 'backslashreplace') + for opt in '-l', '--list': + out = self.tarfilecmd(opt, tar_name, + PYTHONIOENCODING='ascii') + self.assertEqual(out, expected) def test_list_command_verbose(self): - self.make_simple_tarfile(tmpname) - with support.captured_stdout() as t: - with tarfile.open(tmpname, 'r') as tf: - tf.list(verbose=True) - expected = t.getvalue().encode(sys.getfilesystemencoding()) - for opt in '-v', '--verbose': - out = self.tarfilecmd(opt, '-l', tmpname) - self.assertEqual(out, expected) + for tar_name in testtarnames: + with support.captured_stdout() as t: + with tarfile.open(tar_name, 'r') as tf: + tf.list(verbose=True) + expected = t.getvalue().encode('ascii', 'backslashreplace') + for opt in '-v', '--verbose': + out = self.tarfilecmd(opt, '-l', tar_name, + PYTHONIOENCODING='ascii') + self.assertEqual(out, expected) def test_list_command_invalid_file(self): zipname = support.findfile('zipdir.zip') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,9 @@ Library ------- +- Issue #19920: TarFile.list() no longer fails when outputs a listing + containing non-encodable characters. Based on patch by Vajrasky Kok. + - Issue #20515: Fix NULL pointer dereference introduced by issue #20368. - Issue #19186: Restore namespacing of expat symbols inside the pyexpat module. @@ -118,6 +121,8 @@ Tests ----- +- Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. + - Issue #19990: Added tests for the imghdr module. Based on patch by Claudiu Popa. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 19:55:32 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 5 Feb 2014 19:55:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE5OTIw?= =?utf-8?q?=3A_Added_tests_for_TarFile=2Elist=28=29=2E_Based_on_patch_by_V?= =?utf-8?q?ajrasky_Kok=2E?= Message-ID: <3fKBmh2Z9Dz7Ljj@mail.python.org> http://hg.python.org/cpython/rev/48c5c18110ae changeset: 88976:48c5c18110ae branch: 2.7 parent: 88969:07e7bb29a2c5 user: Serhiy Storchaka date: Wed Feb 05 20:55:13 2014 +0200 summary: Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. files: Lib/test/test_tarfile.py | 77 ++++++++++++++++++++++++++++ Misc/NEWS | 2 + 2 files changed, 79 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -158,6 +158,80 @@ self._test_fileobj_link("symtype2", "ustar/regtype") +class ListTest(ReadTest, unittest.TestCase): + + # Override setUp to use default encoding (UTF-8) + def setUp(self): + self.tar = tarfile.open(self.tarname, mode=self.mode) + + def test_list(self): + with test_support.captured_stdout() as t: + self.tar.list(verbose=False) + out = t.getvalue() + self.assertIn('ustar/conttype', out) + self.assertIn('ustar/regtype', out) + self.assertIn('ustar/lnktype', out) + self.assertIn('ustar' + ('/12345' * 40) + '67/longname', out) + self.assertIn('./ustar/linktest2/symtype', out) + self.assertIn('./ustar/linktest2/lnktype', out) + # Make sure it puts trailing slash for directory + self.assertIn('ustar/dirtype/', out) + self.assertIn('ustar/dirtype-with-size/', out) + # Make sure it is able to print non-ASCII characters + self.assertIn('ustar/umlauts-' + '\xc4\xd6\xdc\xe4\xf6\xfc\xdf', out) + self.assertIn('misc/regtype-hpux-signed-chksum-' + '\xc4\xd6\xdc\xe4\xf6\xfc\xdf', out) + self.assertIn('misc/regtype-old-v7-signed-chksum-' + '\xc4\xd6\xdc\xe4\xf6\xfc\xdf', out) + # Make sure it prints files separated by one newline without any + # 'ls -l'-like accessories if verbose flag is not being used + # ... + # ustar/conttype + # ustar/regtype + # ... + self.assertRegexpMatches(out, r'ustar/conttype ?\r?\n' + r'ustar/regtype ?\r?\n') + # Make sure it does not print the source of link without verbose flag + self.assertNotIn('link to', out) + self.assertNotIn('->', out) + + def test_list_verbose(self): + with test_support.captured_stdout() as t: + self.tar.list(verbose=True) + out = t.getvalue() + # Make sure it prints files separated by one newline with 'ls -l'-like + # accessories if verbose flag is being used + # ... + # ?rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/conttype + # ?rw-r--r-- tarfile/tarfile 7011 2003-01-06 07:19:43 ustar/regtype + # ... + self.assertRegexpMatches(out, (r'-rw-r--r-- tarfile/tarfile\s+7011 ' + r'\d{4}-\d\d-\d\d\s+\d\d:\d\d:\d\d ' + r'ustar/\w+type ?\r?\n') * 2) + # Make sure it prints the source of link with verbose flag + self.assertIn('ustar/symtype -> regtype', out) + self.assertIn('./ustar/linktest2/symtype -> ../linktest1/regtype', out) + self.assertIn('./ustar/linktest2/lnktype link to ' + './ustar/linktest1/regtype', out) + self.assertIn('gnu' + ('/123' * 125) + '/longlink link to gnu' + + ('/123' * 125) + '/longname', out) + self.assertIn('pax' + ('/123' * 125) + '/longlink link to pax' + + ('/123' * 125) + '/longname', out) + + +class GzipListTest(ListTest): + tarname = gzipname + mode = "r:gz" + taropen = tarfile.TarFile.gzopen + + +class Bz2ListTest(ListTest): + tarname = bz2name + mode = "r:bz2" + taropen = tarfile.TarFile.bz2open + + class CommonReadTest(ReadTest): def test_empty_tarfile(self): @@ -1646,6 +1720,7 @@ MemberReadTest, GNUReadTest, PaxReadTest, + ListTest, WriteTest, StreamWriteTest, GNUWriteTest, @@ -1677,6 +1752,7 @@ GzipMiscReadTest, GzipUstarReadTest, GzipStreamReadTest, + GzipListTest, GzipWriteTest, GzipStreamWriteTest, ] @@ -1691,6 +1767,7 @@ Bz2MiscReadTest, Bz2UstarReadTest, Bz2StreamReadTest, + Bz2ListTest, Bz2WriteTest, Bz2StreamWriteTest, Bz2PartialReadTest, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -224,6 +224,8 @@ Tests ----- +- Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. + - Issue #19990: Added tests for the imghdr module. Based on patch by Claudiu Popa. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 20:56:52 2014 From: python-checkins at python.org (r.david.murray) Date: Wed, 5 Feb 2014 20:56:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE0NTE1OiBjbGFy?= =?utf-8?q?ify_that_TemporaryDirectory=27s_=5F=5Fenter=5F=5F_returns_the_n?= =?utf-8?q?ame=2E?= Message-ID: <3fKD7S4swpz7LjW@mail.python.org> http://hg.python.org/cpython/rev/b5fe07d39e16 changeset: 88977:b5fe07d39e16 branch: 3.3 parent: 88974:a5895fca91f3 user: R David Murray date: Wed Feb 05 14:53:40 2014 -0500 summary: #14515: clarify that TemporaryDirectory's __enter__ returns the name. files: Doc/library/tempfile.rst | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst --- a/Doc/library/tempfile.rst +++ b/Doc/library/tempfile.rst @@ -97,12 +97,14 @@ This function creates a temporary directory using :func:`mkdtemp` (the supplied arguments are passed directly to the underlying function). The resulting object can be used as a context manager (see - :ref:`context-managers`). On completion of the context (or destruction - of the temporary directory object), the newly created temporary directory + :ref:`context-managers`). On completion of the context or destruction + of the temporary directory object the newly created temporary directory and all its contents are removed from the filesystem. - The directory name can be retrieved from the :attr:`name` attribute - of the returned object. + The directory name can be retrieved from the :attr:`name` attribute of the + returned object. When the returned object is used as a context manager, the + :attr:`name` will be assigned to the target of the :keyword:`as` clause in + the :keyword:`with` statement, if there is one. The directory can be explicitly cleaned up by calling the :func:`cleanup` method. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 5 20:56:53 2014 From: python-checkins at python.org (r.david.murray) Date: Wed, 5 Feb 2014 20:56:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_=2314515=3A_clarify_that_TemporaryDirectory=27s_=5F=5Fen?= =?utf-8?q?ter=5F=5F_returns_the_name=2E?= Message-ID: <3fKD7T6CY1z7Ljj@mail.python.org> http://hg.python.org/cpython/rev/7b7e17723787 changeset: 88978:7b7e17723787 parent: 88975:077aa6d4f3b7 parent: 88977:b5fe07d39e16 user: R David Murray date: Wed Feb 05 14:56:39 2014 -0500 summary: #14515: clarify that TemporaryDirectory's __enter__ returns the name. files: Doc/library/tempfile.rst | 10 ++++++---- 1 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst --- a/Doc/library/tempfile.rst +++ b/Doc/library/tempfile.rst @@ -97,12 +97,14 @@ This function creates a temporary directory using :func:`mkdtemp` (the supplied arguments are passed directly to the underlying function). The resulting object can be used as a context manager (see - :ref:`context-managers`). On completion of the context (or destruction - of the temporary directory object), the newly created temporary directory + :ref:`context-managers`). On completion of the context or destruction + of the temporary directory object the newly created temporary directory and all its contents are removed from the filesystem. - The directory name can be retrieved from the :attr:`name` attribute - of the returned object. + The directory name can be retrieved from the :attr:`name` attribute of the + returned object. When the returned object is used as a context manager, the + :attr:`name` will be assigned to the target of the :keyword:`as` clause in + the :keyword:`with` statement, if there is one. The directory can be explicitly cleaned up by calling the :func:`cleanup` method. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 00:11:44 2014 From: python-checkins at python.org (yury.selivanov) Date: Thu, 6 Feb 2014 00:11:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Estreams=3A_Use_b?= =?utf-8?q?ytebuffer_in_StreamReader=3B_Add_assertion_in_feed=5Fdata?= Message-ID: <3fKJSJ5SL5z7LjW@mail.python.org> http://hg.python.org/cpython/rev/260d6e1e9b0f changeset: 88979:260d6e1e9b0f user: Yury Selivanov date: Wed Feb 05 18:11:13 2014 -0500 summary: asyncio.streams: Use bytebuffer in StreamReader; Add assertion in feed_data files: Lib/asyncio/streams.py | 71 ++++--------- Lib/test/test_asyncio/test_streams.py | 79 +++++++++----- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -4,8 +4,6 @@ 'open_connection', 'start_server', 'IncompleteReadError', ] -import collections - from . import events from . import futures from . import protocols @@ -259,9 +257,7 @@ if loop is None: loop = events.get_event_loop() self._loop = loop - # TODO: Use a bytearray for a buffer, like the transport. - self._buffer = collections.deque() # Deque of bytes objects. - self._byte_count = 0 # Bytes in buffer. + self._buffer = bytearray() self._eof = False # Whether we're done. self._waiter = None # A future. self._exception = None @@ -285,7 +281,7 @@ self._transport = transport def _maybe_resume_transport(self): - if self._paused and self._byte_count <= self._limit: + if self._paused and len(self._buffer) <= self._limit: self._paused = False self._transport.resume_reading() @@ -298,11 +294,12 @@ waiter.set_result(True) def feed_data(self, data): + assert not self._eof, 'feed_data after feed_eof' + if not data: return - self._buffer.append(data) - self._byte_count += len(data) + self._buffer.extend(data) waiter = self._waiter if waiter is not None: @@ -312,7 +309,7 @@ if (self._transport is not None and not self._paused and - self._byte_count > 2*self._limit): + len(self._buffer) > 2*self._limit): try: self._transport.pause_reading() except NotImplementedError: @@ -338,28 +335,22 @@ if self._exception is not None: raise self._exception - parts = [] - parts_size = 0 + line = bytearray() not_enough = True while not_enough: while self._buffer and not_enough: - data = self._buffer.popleft() - ichar = data.find(b'\n') + ichar = self._buffer.find(b'\n') if ichar < 0: - parts.append(data) - parts_size += len(data) + line.extend(self._buffer) + self._buffer.clear() else: ichar += 1 - head, tail = data[:ichar], data[ichar:] - if tail: - self._buffer.appendleft(tail) + line.extend(self._buffer[:ichar]) + del self._buffer[:ichar] not_enough = False - parts.append(head) - parts_size += len(head) - if parts_size > self._limit: - self._byte_count -= parts_size + if len(line) > self._limit: self._maybe_resume_transport() raise ValueError('Line is too long') @@ -373,11 +364,8 @@ finally: self._waiter = None - line = b''.join(parts) - self._byte_count -= parts_size self._maybe_resume_transport() - - return line + return bytes(line) @tasks.coroutine def read(self, n=-1): @@ -395,36 +383,23 @@ finally: self._waiter = None else: - if not self._byte_count and not self._eof: + if not self._buffer and not self._eof: self._waiter = self._create_waiter('read') try: yield from self._waiter finally: self._waiter = None - if n < 0 or self._byte_count <= n: - data = b''.join(self._buffer) + if n < 0 or len(self._buffer) <= n: + data = bytes(self._buffer) self._buffer.clear() - self._byte_count = 0 - self._maybe_resume_transport() - return data + else: + # n > 0 and len(self._buffer) > n + data = bytes(self._buffer[:n]) + del self._buffer[:n] - parts = [] - parts_bytes = 0 - while self._buffer and parts_bytes < n: - data = self._buffer.popleft() - data_bytes = len(data) - if n < parts_bytes + data_bytes: - data_bytes = n - parts_bytes - data, rest = data[:data_bytes], data[data_bytes:] - self._buffer.appendleft(rest) - - parts.append(data) - parts_bytes += data_bytes - self._byte_count -= data_bytes - self._maybe_resume_transport() - - return b''.join(parts) + self._maybe_resume_transport() + return data @tasks.coroutine def readexactly(self, n): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -79,13 +79,13 @@ stream = asyncio.StreamReader(loop=self.loop) stream.feed_data(b'') - self.assertEqual(0, stream._byte_count) + self.assertEqual(b'', stream._buffer) - def test_feed_data_byte_count(self): + def test_feed_nonempty_data(self): stream = asyncio.StreamReader(loop=self.loop) stream.feed_data(self.DATA) - self.assertEqual(len(self.DATA), stream._byte_count) + self.assertEqual(self.DATA, stream._buffer) def test_read_zero(self): # Read zero bytes. @@ -94,7 +94,7 @@ data = self.loop.run_until_complete(stream.read(0)) self.assertEqual(b'', data) - self.assertEqual(len(self.DATA), stream._byte_count) + self.assertEqual(self.DATA, stream._buffer) def test_read(self): # Read bytes. @@ -107,7 +107,7 @@ data = self.loop.run_until_complete(read_task) self.assertEqual(self.DATA, data) - self.assertFalse(stream._byte_count) + self.assertEqual(b'', stream._buffer) def test_read_line_breaks(self): # Read bytes without line breaks. @@ -118,7 +118,7 @@ data = self.loop.run_until_complete(stream.read(5)) self.assertEqual(b'line1', data) - self.assertEqual(5, stream._byte_count) + self.assertEqual(b'line2', stream._buffer) def test_read_eof(self): # Read bytes, stop at eof. @@ -131,7 +131,7 @@ data = self.loop.run_until_complete(read_task) self.assertEqual(b'', data) - self.assertFalse(stream._byte_count) + self.assertEqual(b'', stream._buffer) def test_read_until_eof(self): # Read all bytes until eof. @@ -147,7 +147,7 @@ data = self.loop.run_until_complete(read_task) self.assertEqual(b'chunk1\nchunk2', data) - self.assertFalse(stream._byte_count) + self.assertEqual(b'', stream._buffer) def test_read_exception(self): stream = asyncio.StreamReader(loop=self.loop) @@ -161,7 +161,8 @@ ValueError, self.loop.run_until_complete, stream.read(2)) def test_readline(self): - # Read one line. + # Read one line. 'readline' will need to wait for the data + # to come from 'cb' stream = asyncio.StreamReader(loop=self.loop) stream.feed_data(b'chunk1 ') read_task = asyncio.Task(stream.readline(), loop=self.loop) @@ -174,30 +175,40 @@ line = self.loop.run_until_complete(read_task) self.assertEqual(b'chunk1 chunk2 chunk3 \n', line) - self.assertEqual(len(b'\n chunk4')-1, stream._byte_count) + self.assertEqual(b' chunk4', stream._buffer) def test_readline_limit_with_existing_data(self): - stream = asyncio.StreamReader(3, loop=self.loop) + # Read one line. The data is in StreamReader's buffer + # before the event loop is run. + + stream = asyncio.StreamReader(limit=3, loop=self.loop) stream.feed_data(b'li') stream.feed_data(b'ne1\nline2\n') self.assertRaises( ValueError, self.loop.run_until_complete, stream.readline()) - self.assertEqual([b'line2\n'], list(stream._buffer)) + # The buffer should contain the remaining data after exception + self.assertEqual(b'line2\n', stream._buffer) - stream = asyncio.StreamReader(3, loop=self.loop) + stream = asyncio.StreamReader(limit=3, loop=self.loop) stream.feed_data(b'li') stream.feed_data(b'ne1') stream.feed_data(b'li') self.assertRaises( ValueError, self.loop.run_until_complete, stream.readline()) - self.assertEqual([b'li'], list(stream._buffer)) - self.assertEqual(2, stream._byte_count) + # No b'\n' at the end. The 'limit' is set to 3. So before + # waiting for the new data in buffer, 'readline' will consume + # the entire buffer, and since the length of the consumed data + # is more than 3, it will raise a ValudError. The buffer is + # expected to be empty now. + self.assertEqual(b'', stream._buffer) def test_readline_limit(self): - stream = asyncio.StreamReader(7, loop=self.loop) + # Read one line. StreamReaders are fed with data after + # their 'readline' methods are called. + stream = asyncio.StreamReader(limit=7, loop=self.loop) def cb(): stream.feed_data(b'chunk1') stream.feed_data(b'chunk2') @@ -207,10 +218,25 @@ self.assertRaises( ValueError, self.loop.run_until_complete, stream.readline()) - self.assertEqual([b'chunk3\n'], list(stream._buffer)) - self.assertEqual(7, stream._byte_count) + # The buffer had just one line of data, and after raising + # a ValueError it should be empty. + self.assertEqual(b'', stream._buffer) - def test_readline_line_byte_count(self): + stream = asyncio.StreamReader(limit=7, loop=self.loop) + def cb(): + stream.feed_data(b'chunk1') + stream.feed_data(b'chunk2\n') + stream.feed_data(b'chunk3\n') + stream.feed_eof() + self.loop.call_soon(cb) + + self.assertRaises( + ValueError, self.loop.run_until_complete, stream.readline()) + self.assertEqual(b'chunk3\n', stream._buffer) + + def test_readline_nolimit_nowait(self): + # All needed data for the first 'readline' call will be + # in the buffer. stream = asyncio.StreamReader(loop=self.loop) stream.feed_data(self.DATA[:6]) stream.feed_data(self.DATA[6:]) @@ -218,7 +244,7 @@ line = self.loop.run_until_complete(stream.readline()) self.assertEqual(b'line1\n', line) - self.assertEqual(len(self.DATA) - len(b'line1\n'), stream._byte_count) + self.assertEqual(b'line2\nline3\n', stream._buffer) def test_readline_eof(self): stream = asyncio.StreamReader(loop=self.loop) @@ -244,9 +270,7 @@ data = self.loop.run_until_complete(stream.read(7)) self.assertEqual(b'line2\nl', data) - self.assertEqual( - len(self.DATA) - len(b'line1\n') - len(b'line2\nl'), - stream._byte_count) + self.assertEqual(b'ine3\n', stream._buffer) def test_readline_exception(self): stream = asyncio.StreamReader(loop=self.loop) @@ -258,6 +282,7 @@ stream.set_exception(ValueError()) self.assertRaises( ValueError, self.loop.run_until_complete, stream.readline()) + self.assertEqual(b'', stream._buffer) def test_readexactly_zero_or_less(self): # Read exact number of bytes (zero or less). @@ -266,11 +291,11 @@ data = self.loop.run_until_complete(stream.readexactly(0)) self.assertEqual(b'', data) - self.assertEqual(len(self.DATA), stream._byte_count) + self.assertEqual(self.DATA, stream._buffer) data = self.loop.run_until_complete(stream.readexactly(-1)) self.assertEqual(b'', data) - self.assertEqual(len(self.DATA), stream._byte_count) + self.assertEqual(self.DATA, stream._buffer) def test_readexactly(self): # Read exact number of bytes. @@ -287,7 +312,7 @@ data = self.loop.run_until_complete(read_task) self.assertEqual(self.DATA + self.DATA, data) - self.assertEqual(len(self.DATA), stream._byte_count) + self.assertEqual(self.DATA, stream._buffer) def test_readexactly_eof(self): # Read exact number of bytes (eof). @@ -306,7 +331,7 @@ self.assertEqual(cm.exception.expected, n) self.assertEqual(str(cm.exception), '18 bytes read on a total of 36 expected bytes') - self.assertFalse(stream._byte_count) + self.assertEqual(b'', stream._buffer) def test_readexactly_exception(self): stream = asyncio.StreamReader(loop=self.loop) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 01:55:51 2014 From: python-checkins at python.org (ned.deily) Date: Thu, 6 Feb 2014 01:55:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwMzc0?= =?utf-8?q?=3A_Avoid_compiler_warnings_when_compiling_readline_with_libedi?= =?utf-8?q?t=2E?= Message-ID: <3fKLmR6r2zz7LjW@mail.python.org> http://hg.python.org/cpython/rev/0b5b0bfcc7b1 changeset: 88980:0b5b0bfcc7b1 branch: 2.7 parent: 88976:48c5c18110ae user: Ned Deily date: Wed Feb 05 16:52:26 2014 -0800 summary: Issue #20374: Avoid compiler warnings when compiling readline with libedit. files: Modules/readline.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -749,15 +749,24 @@ return result; } + static int +#if defined(_RL_FUNCTION_TYPEDEF) on_startup_hook(void) +#else +on_startup_hook() +#endif { return on_hook(startup_hook); } #ifdef HAVE_RL_PRE_INPUT_HOOK static int +#if defined(_RL_FUNCTION_TYPEDEF) on_pre_input_hook(void) +#else +on_pre_input_hook() +#endif { return on_hook(pre_input_hook); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 01:55:53 2014 From: python-checkins at python.org (ned.deily) Date: Thu, 6 Feb 2014 01:55:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwMzc0?= =?utf-8?q?=3A_Avoid_compiler_warnings_when_compiling_readline_with_libedi?= =?utf-8?q?t=2E?= Message-ID: <3fKLmT5JQQz7Lkb@mail.python.org> http://hg.python.org/cpython/rev/9131a9edcac4 changeset: 88981:9131a9edcac4 branch: 3.3 parent: 88977:b5fe07d39e16 user: Ned Deily date: Wed Feb 05 16:53:10 2014 -0800 summary: Issue #20374: Avoid compiler warnings when compiling readline with libedit. files: Modules/readline.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -773,15 +773,24 @@ return result; } + static int +#if defined(_RL_FUNCTION_TYPEDEF) on_startup_hook(void) +#else +on_startup_hook() +#endif { return on_hook(startup_hook); } #ifdef HAVE_RL_PRE_INPUT_HOOK static int +#if defined(_RL_FUNCTION_TYPEDEF) on_pre_input_hook(void) +#else +on_pre_input_hook() +#endif { return on_hook(pre_input_hook); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 01:55:55 2014 From: python-checkins at python.org (ned.deily) Date: Thu, 6 Feb 2014 01:55:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320374=3A_merge?= Message-ID: <3fKLmW017mz7Lkl@mail.python.org> http://hg.python.org/cpython/rev/0abf103f5559 changeset: 88982:0abf103f5559 parent: 88979:260d6e1e9b0f parent: 88981:9131a9edcac4 user: Ned Deily date: Wed Feb 05 16:55:20 2014 -0800 summary: Issue #20374: merge files: Modules/readline.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -815,8 +815,13 @@ return result; } + static int +#if defined(_RL_FUNCTION_TYPEDEF) on_startup_hook(void) +#else +on_startup_hook() +#endif { int r; #ifdef WITH_THREAD @@ -831,7 +836,11 @@ #ifdef HAVE_RL_PRE_INPUT_HOOK static int +#if defined(_RL_FUNCTION_TYPEDEF) on_pre_input_hook(void) +#else +on_pre_input_hook() +#endif { int r; #ifdef WITH_THREAD -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 02:04:29 2014 From: python-checkins at python.org (ned.deily) Date: Thu, 6 Feb 2014 02:04:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwMzc0?= =?utf-8?q?=3A_delete_spurious_empty_line?= Message-ID: <3fKLyP1Bfcz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/74c7a6fd8b45 changeset: 88983:74c7a6fd8b45 branch: 2.7 parent: 88980:0b5b0bfcc7b1 user: Ned Deily date: Wed Feb 05 17:01:41 2014 -0800 summary: Issue #20374: delete spurious empty line files: Modules/readline.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -749,7 +749,6 @@ return result; } - static int #if defined(_RL_FUNCTION_TYPEDEF) on_startup_hook(void) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 02:04:30 2014 From: python-checkins at python.org (ned.deily) Date: Thu, 6 Feb 2014 02:04:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwMzc0?= =?utf-8?q?=3A_delete_spurious_empty_line?= Message-ID: <3fKLyQ2vV6z7Ljh@mail.python.org> http://hg.python.org/cpython/rev/6616c94d6149 changeset: 88984:6616c94d6149 branch: 3.3 parent: 88981:9131a9edcac4 user: Ned Deily date: Wed Feb 05 17:02:29 2014 -0800 summary: Issue #20374: delete spurious empty line files: Modules/readline.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -773,7 +773,6 @@ return result; } - static int #if defined(_RL_FUNCTION_TYPEDEF) on_startup_hook(void) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 02:04:31 2014 From: python-checkins at python.org (ned.deily) Date: Thu, 6 Feb 2014 02:04:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320374=3A_merge?= Message-ID: <3fKLyR4b4qz7Ljc@mail.python.org> http://hg.python.org/cpython/rev/0b91e764b889 changeset: 88985:0b91e764b889 parent: 88982:0abf103f5559 parent: 88984:6616c94d6149 user: Ned Deily date: Wed Feb 05 17:03:42 2014 -0800 summary: Issue #20374: merge files: Modules/readline.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -815,7 +815,6 @@ return result; } - static int #if defined(_RL_FUNCTION_TYPEDEF) on_startup_hook(void) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 06:19:08 2014 From: python-checkins at python.org (yury.selivanov) Date: Thu, 6 Feb 2014 06:19:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Estreams=2EStream?= =?utf-8?b?UmVhZGVyOiBBZGQgJ2F0X2VvZigpJyBtZXRob2Q=?= Message-ID: <3fKScD26KPz7LjR@mail.python.org> http://hg.python.org/cpython/rev/4a3761dedbd2 changeset: 88986:4a3761dedbd2 parent: 88979:260d6e1e9b0f user: Yury Selivanov date: Thu Feb 06 00:14:30 2014 -0500 summary: asyncio.streams.StreamReader: Add 'at_eof()' method files: Lib/asyncio/streams.py | 4 ++++ Lib/test/test_asyncio/test_streams.py | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -293,6 +293,10 @@ if not waiter.cancelled(): waiter.set_result(True) + def at_eof(self): + """Return True if the buffer is empty and 'feed_eof' was called.""" + return self._eof and not self._buffer + def feed_data(self, data): assert not self._eof, 'feed_data after feed_eof' diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -204,6 +204,21 @@ # expected to be empty now. self.assertEqual(b'', stream._buffer) + def test_at_eof(self): + stream = asyncio.StreamReader(loop=self.loop) + self.assertFalse(stream.at_eof()) + + stream.feed_data(b'some data\n') + self.assertFalse(stream.at_eof()) + + self.loop.run_until_complete(stream.readline()) + self.assertFalse(stream.at_eof()) + + stream.feed_data(b'some data\n') + stream.feed_eof() + self.loop.run_until_complete(stream.readline()) + self.assertTrue(stream.at_eof()) + def test_readline_limit(self): # Read one line. StreamReaders are fed with data after # their 'readline' methods are called. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 06:19:09 2014 From: python-checkins at python.org (yury.selivanov) Date: Thu, 6 Feb 2014 06:19:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge_heads?= Message-ID: <3fKScF3pnwz7LjR@mail.python.org> http://hg.python.org/cpython/rev/259857de72e1 changeset: 88987:259857de72e1 parent: 88986:4a3761dedbd2 parent: 88985:0b91e764b889 user: Yury Selivanov date: Thu Feb 06 00:18:48 2014 -0500 summary: merge heads files: Modules/readline.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -816,7 +816,11 @@ } static int +#if defined(_RL_FUNCTION_TYPEDEF) on_startup_hook(void) +#else +on_startup_hook() +#endif { int r; #ifdef WITH_THREAD @@ -831,7 +835,11 @@ #ifdef HAVE_RL_PRE_INPUT_HOOK static int +#if defined(_RL_FUNCTION_TYPEDEF) on_pre_input_hook(void) +#else +on_pre_input_hook() +#endif { int r; #ifdef WITH_THREAD -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 08:28:02 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 6 Feb 2014 08:28:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTIw?= =?utf-8?q?=3A_Fixed_readline_test_in_test=5Fcodecs=2E?= Message-ID: <3fKWSy1zXqz7LjM@mail.python.org> http://hg.python.org/cpython/rev/305b6a5da852 changeset: 88988:305b6a5da852 branch: 2.7 parent: 88983:74c7a6fd8b45 user: Serhiy Storchaka date: Thu Feb 06 09:26:32 2014 +0200 summary: Issue #20520: Fixed readline test in test_codecs. files: Lib/test/test_codecs.py | 21 +++++++++++++++------ 1 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -97,19 +97,20 @@ self.assertEqual(readalllines(s, True, 10), sexpected) self.assertEqual(readalllines(s, False, 10), sexpectednoends) + lineends = ("\n", "\r\n", "\r", u"\u2028") # Test long lines (multiple calls to read() in readline()) vw = [] vwo = [] - for (i, lineend) in enumerate(u"\n \r\n \r \u2028".split()): - vw.append((i*200)*u"\3042" + lineend) - vwo.append((i*200)*u"\3042") - self.assertEqual(readalllines("".join(vw), True), "".join(vw)) - self.assertEqual(readalllines("".join(vw), False),"".join(vwo)) + for (i, lineend) in enumerate(lineends): + vw.append((i*200+200)*u"\u3042" + lineend) + vwo.append((i*200+200)*u"\u3042") + self.assertEqual(readalllines("".join(vw), True), "|".join(vw)) + self.assertEqual(readalllines("".join(vw), False), "|".join(vwo)) # Test lines where the first read might end with \r, so the # reader has to look ahead whether this is a lone \r or a \r\n for size in xrange(80): - for lineend in u"\n \r\n \r \u2028".split(): + for lineend in lineends: s = 10*(size*u"a" + lineend + u"xxx\n") reader = getreader(s) for i in xrange(10): @@ -117,12 +118,20 @@ reader.readline(keepends=True), size*u"a" + lineend, ) + self.assertEqual( + reader.readline(keepends=True), + "xxx\n", + ) reader = getreader(s) for i in xrange(10): self.assertEqual( reader.readline(keepends=False), size*u"a", ) + self.assertEqual( + reader.readline(keepends=False), + "xxx", + ) def test_mixed_readline_and_read(self): lines = ["Humpty Dumpty sat on a wall,\n", -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 08:28:03 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 6 Feb 2014 08:28:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTIw?= =?utf-8?q?=3A_Fixed_readline_test_in_test=5Fcodecs=2E?= Message-ID: <3fKWSz3nYTz7LjM@mail.python.org> http://hg.python.org/cpython/rev/82d374a9bbc7 changeset: 88989:82d374a9bbc7 branch: 3.3 parent: 88984:6616c94d6149 user: Serhiy Storchaka date: Thu Feb 06 09:26:56 2014 +0200 summary: Issue #20520: Fixed readline test in test_codecs. files: Lib/test/test_codecs.py | 21 +++++++++++++++------ 1 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -146,19 +146,20 @@ self.assertEqual(readalllines(s, True, 10), sexpected) self.assertEqual(readalllines(s, False, 10), sexpectednoends) + lineends = ("\n", "\r\n", "\r", "\u2028") # Test long lines (multiple calls to read() in readline()) vw = [] vwo = [] - for (i, lineend) in enumerate("\n \r\n \r \u2028".split()): - vw.append((i*200)*"\3042" + lineend) - vwo.append((i*200)*"\3042") - self.assertEqual(readalllines("".join(vw), True), "".join(vw)) - self.assertEqual(readalllines("".join(vw), False),"".join(vwo)) + for (i, lineend) in enumerate(lineends): + vw.append((i*200+200)*"\u3042" + lineend) + vwo.append((i*200+200)*"\u3042") + self.assertEqual(readalllines("".join(vw), True), "|".join(vw)) + self.assertEqual(readalllines("".join(vw), False), "|".join(vwo)) # Test lines where the first read might end with \r, so the # reader has to look ahead whether this is a lone \r or a \r\n for size in range(80): - for lineend in "\n \r\n \r \u2028".split(): + for lineend in lineends: s = 10*(size*"a" + lineend + "xxx\n") reader = getreader(s) for i in range(10): @@ -166,12 +167,20 @@ reader.readline(keepends=True), size*"a" + lineend, ) + self.assertEqual( + reader.readline(keepends=True), + "xxx\n", + ) reader = getreader(s) for i in range(10): self.assertEqual( reader.readline(keepends=False), size*"a", ) + self.assertEqual( + reader.readline(keepends=False), + "xxx", + ) def test_mixed_readline_and_read(self): lines = ["Humpty Dumpty sat on a wall,\n", -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 08:28:04 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 6 Feb 2014 08:28:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320520=3A_Fixed_readline_test_in_test=5Fcodecs?= =?utf-8?q?=2E?= Message-ID: <3fKWT05Fhjz7LlQ@mail.python.org> http://hg.python.org/cpython/rev/1457fa0da200 changeset: 88990:1457fa0da200 parent: 88987:259857de72e1 parent: 88989:82d374a9bbc7 user: Serhiy Storchaka date: Thu Feb 06 09:27:28 2014 +0200 summary: Issue #20520: Fixed readline test in test_codecs. files: Lib/test/test_codecs.py | 21 +++++++++++++++------ 1 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -148,19 +148,20 @@ self.assertEqual(readalllines(s, True, 10), sexpected) self.assertEqual(readalllines(s, False, 10), sexpectednoends) + lineends = ("\n", "\r\n", "\r", "\u2028") # Test long lines (multiple calls to read() in readline()) vw = [] vwo = [] - for (i, lineend) in enumerate("\n \r\n \r \u2028".split()): - vw.append((i*200)*"\3042" + lineend) - vwo.append((i*200)*"\3042") - self.assertEqual(readalllines("".join(vw), True), "".join(vw)) - self.assertEqual(readalllines("".join(vw), False),"".join(vwo)) + for (i, lineend) in enumerate(lineends): + vw.append((i*200+200)*"\u3042" + lineend) + vwo.append((i*200+200)*"\u3042") + self.assertEqual(readalllines("".join(vw), True), "|".join(vw)) + self.assertEqual(readalllines("".join(vw), False), "|".join(vwo)) # Test lines where the first read might end with \r, so the # reader has to look ahead whether this is a lone \r or a \r\n for size in range(80): - for lineend in "\n \r\n \r \u2028".split(): + for lineend in lineends: s = 10*(size*"a" + lineend + "xxx\n") reader = getreader(s) for i in range(10): @@ -168,12 +169,20 @@ reader.readline(keepends=True), size*"a" + lineend, ) + self.assertEqual( + reader.readline(keepends=True), + "xxx\n", + ) reader = getreader(s) for i in range(10): self.assertEqual( reader.readline(keepends=False), size*"a", ) + self.assertEqual( + reader.readline(keepends=False), + "xxx", + ) def test_mixed_readline_and_read(self): lines = ["Humpty Dumpty sat on a wall,\n", -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Feb 6 09:49:07 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 06 Feb 2014 09:49:07 +0100 Subject: [Python-checkins] Daily reference leaks (0b91e764b889): sum=0 Message-ID: results for 0b91e764b889 on branch "default" -------------------------------------------- test_site leaked [-2, 2, 0] references, sum=0 test_site leaked [-2, 2, 0] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogXZyqG1', '-x'] From python-checkins at python.org Thu Feb 6 11:19:37 2014 From: python-checkins at python.org (ronald.oussoren) Date: Thu, 6 Feb 2014 11:19:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2314455=3A_fix_hand?= =?utf-8?q?ling_of_unsigned_long_long_values_for_binary_plist_files?= Message-ID: <3fKbGx2vyLz7LjN@mail.python.org> http://hg.python.org/cpython/rev/0121c2b7dcce changeset: 88991:0121c2b7dcce user: Ronald Oussoren date: Thu Feb 06 11:19:18 2014 +0100 summary: Issue #14455: fix handling of unsigned long long values for binary plist files Values in the range of an unsigned long long, but outside of the range of a signed long long were serialized as a negative value. Due to a bug in PyObjC my test scripts indicated that the previous behavior matched Apple's plist code, instead the handle large unsigned values correctly. The change to plistlib.py is from a patch by Serhiy. files: Doc/library/plistlib.rst | 7 - Lib/plistlib.py | 11 +- Lib/test/test_plistlib.py | 132 ++++++----- Mac/Tools/plistlib_generate_testdata.py | 3 +- Misc/NEWS | 4 + 5 files changed, 79 insertions(+), 78 deletions(-) diff --git a/Doc/library/plistlib.rst b/Doc/library/plistlib.rst --- a/Doc/library/plistlib.rst +++ b/Doc/library/plistlib.rst @@ -107,13 +107,6 @@ An :exc:`OverflowError` will be raised for integer values that cannot be represented in (binary) plist files. - .. warning:: - - For compatibility with Apple's libraries it is possible to write - an integer in the range from 2 ** 63 upto (and including) 2 ** 64 - to binary plists, even though these will be read back as negative - values. - .. versionadded: 3.4 diff --git a/Lib/plistlib.py b/Lib/plistlib.py --- a/Lib/plistlib.py +++ b/Lib/plistlib.py @@ -879,18 +879,19 @@ try: self._fp.write(struct.pack('>Bq', 0x13, value)) except struct.error: - raise OverflowError(value) + raise OverflowError(value) from None elif value < 1 << 8: self._fp.write(struct.pack('>BB', 0x10, value)) elif value < 1 << 16: self._fp.write(struct.pack('>BH', 0x11, value)) elif value < 1 << 32: self._fp.write(struct.pack('>BL', 0x12, value)) + elif value < 1 << 63: + self._fp.write(struct.pack('>BQ', 0x13, value)) + elif value < 1 << 64: + self._fp.write(b'\x14' + value.to_bytes(16, 'big', signed=True)) else: - try: - self._fp.write(struct.pack('>BQ', 0x13, value)) - except struct.error: - raise OverflowError(value) + raise OverflowError(value) elif isinstance(value, float): self._fp.write(struct.pack('>Bd', 0x23, value)) diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py --- a/Lib/test/test_plistlib.py +++ b/Lib/test/test_plistlib.py @@ -22,72 +22,73 @@ IiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4w LmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8ZGljdD4KCTxrZXk+YUJp Z0ludDwva2V5PgoJPGludGVnZXI+OTIyMzM3MjAzNjg1NDc3NTc2NDwvaW50 - ZWdlcj4KCTxrZXk+YURhdGU8L2tleT4KCTxkYXRlPjIwMDQtMTAtMjZUMTA6 - MzM6MzNaPC9kYXRlPgoJPGtleT5hRGljdDwva2V5PgoJPGRpY3Q+CgkJPGtl - eT5hRmFsc2VWYWx1ZTwva2V5PgoJCTxmYWxzZS8+CgkJPGtleT5hVHJ1ZVZh - bHVlPC9rZXk+CgkJPHRydWUvPgoJCTxrZXk+YVVuaWNvZGVWYWx1ZTwva2V5 - PgoJCTxzdHJpbmc+TcOkc3NpZywgTWHDnzwvc3RyaW5nPgoJCTxrZXk+YW5v - dGhlclN0cmluZzwva2V5PgoJCTxzdHJpbmc+Jmx0O2hlbGxvICZhbXA7ICdo - aScgdGhlcmUhJmd0Ozwvc3RyaW5nPgoJCTxrZXk+ZGVlcGVyRGljdDwva2V5 - PgoJCTxkaWN0PgoJCQk8a2V5PmE8L2tleT4KCQkJPGludGVnZXI+MTc8L2lu - dGVnZXI+CgkJCTxrZXk+Yjwva2V5PgoJCQk8cmVhbD4zMi41PC9yZWFsPgoJ - CQk8a2V5PmM8L2tleT4KCQkJPGFycmF5PgoJCQkJPGludGVnZXI+MTwvaW50 - ZWdlcj4KCQkJCTxpbnRlZ2VyPjI8L2ludGVnZXI+CgkJCQk8c3RyaW5nPnRl - eHQ8L3N0cmluZz4KCQkJPC9hcnJheT4KCQk8L2RpY3Q+Cgk8L2RpY3Q+Cgk8 - a2V5PmFGbG9hdDwva2V5PgoJPHJlYWw+MC41PC9yZWFsPgoJPGtleT5hTGlz - dDwva2V5PgoJPGFycmF5PgoJCTxzdHJpbmc+QTwvc3RyaW5nPgoJCTxzdHJp - bmc+Qjwvc3RyaW5nPgoJCTxpbnRlZ2VyPjEyPC9pbnRlZ2VyPgoJCTxyZWFs - PjMyLjU8L3JlYWw+CgkJPGFycmF5PgoJCQk8aW50ZWdlcj4xPC9pbnRlZ2Vy - PgoJCQk8aW50ZWdlcj4yPC9pbnRlZ2VyPgoJCQk8aW50ZWdlcj4zPC9pbnRl - Z2VyPgoJCTwvYXJyYXk+Cgk8L2FycmF5PgoJPGtleT5hTmVnYXRpdmVCaWdJ - bnQ8L2tleT4KCTxpbnRlZ2VyPi04MDAwMDAwMDAwMDwvaW50ZWdlcj4KCTxr - ZXk+YU5lZ2F0aXZlSW50PC9rZXk+Cgk8aW50ZWdlcj4tNTwvaW50ZWdlcj4K - CTxrZXk+YVN0cmluZzwva2V5PgoJPHN0cmluZz5Eb29kYWg8L3N0cmluZz4K - CTxrZXk+YW5FbXB0eURpY3Q8L2tleT4KCTxkaWN0Lz4KCTxrZXk+YW5FbXB0 - eUxpc3Q8L2tleT4KCTxhcnJheS8+Cgk8a2V5PmFuSW50PC9rZXk+Cgk8aW50 - ZWdlcj43Mjg8L2ludGVnZXI+Cgk8a2V5Pm5lc3RlZERhdGE8L2tleT4KCTxh - cnJheT4KCQk8ZGF0YT4KCQlQR3h2ZEhNZ2IyWWdZbWx1WVhKNUlHZDFibXMr - QUFFQ0F6eHNiM1J6SUc5bUlHSnBibUZ5ZVNCbmRXNXIKCQlQZ0FCQWdNOGJH - OTBjeUJ2WmlCaWFXNWhjbmtnWjNWdWF6NEFBUUlEUEd4dmRITWdiMllnWW1s - dVlYSjUKCQlJR2QxYm1zK0FBRUNBenhzYjNSeklHOW1JR0pwYm1GeWVTQm5k - VzVyUGdBQkFnTThiRzkwY3lCdlppQmkKCQlhVzVoY25rZ1ozVnVhejRBQVFJ - RFBHeHZkSE1nYjJZZ1ltbHVZWEo1SUdkMWJtcytBQUVDQXp4c2IzUnoKCQlJ - RzltSUdKcGJtRnllU0JuZFc1clBnQUJBZ004Ykc5MGN5QnZaaUJpYVc1aGNu - a2daM1Z1YXo0QUFRSUQKCQlQR3h2ZEhNZ2IyWWdZbWx1WVhKNUlHZDFibXMr - QUFFQ0F3PT0KCQk8L2RhdGE+Cgk8L2FycmF5PgoJPGtleT5zb21lRGF0YTwv - a2V5PgoJPGRhdGE+CglQR0pwYm1GeWVTQm5kVzVyUGc9PQoJPC9kYXRhPgoJ - PGtleT5zb21lTW9yZURhdGE8L2tleT4KCTxkYXRhPgoJUEd4dmRITWdiMlln + ZWdlcj4KCTxrZXk+YUJpZ0ludDI8L2tleT4KCTxpbnRlZ2VyPjkyMjMzNzIw + MzY4NTQ3NzU4NTI8L2ludGVnZXI+Cgk8a2V5PmFEYXRlPC9rZXk+Cgk8ZGF0 + ZT4yMDA0LTEwLTI2VDEwOjMzOjMzWjwvZGF0ZT4KCTxrZXk+YURpY3Q8L2tl + eT4KCTxkaWN0PgoJCTxrZXk+YUZhbHNlVmFsdWU8L2tleT4KCQk8ZmFsc2Uv + PgoJCTxrZXk+YVRydWVWYWx1ZTwva2V5PgoJCTx0cnVlLz4KCQk8a2V5PmFV + bmljb2RlVmFsdWU8L2tleT4KCQk8c3RyaW5nPk3DpHNzaWcsIE1hw588L3N0 + cmluZz4KCQk8a2V5PmFub3RoZXJTdHJpbmc8L2tleT4KCQk8c3RyaW5nPiZs + dDtoZWxsbyAmYW1wOyAnaGknIHRoZXJlISZndDs8L3N0cmluZz4KCQk8a2V5 + PmRlZXBlckRpY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5hPC9rZXk+CgkJ + CTxpbnRlZ2VyPjE3PC9pbnRlZ2VyPgoJCQk8a2V5PmI8L2tleT4KCQkJPHJl + YWw+MzIuNTwvcmVhbD4KCQkJPGtleT5jPC9rZXk+CgkJCTxhcnJheT4KCQkJ + CTxpbnRlZ2VyPjE8L2ludGVnZXI+CgkJCQk8aW50ZWdlcj4yPC9pbnRlZ2Vy + PgoJCQkJPHN0cmluZz50ZXh0PC9zdHJpbmc+CgkJCTwvYXJyYXk+CgkJPC9k + aWN0PgoJPC9kaWN0PgoJPGtleT5hRmxvYXQ8L2tleT4KCTxyZWFsPjAuNTwv + cmVhbD4KCTxrZXk+YUxpc3Q8L2tleT4KCTxhcnJheT4KCQk8c3RyaW5nPkE8 + L3N0cmluZz4KCQk8c3RyaW5nPkI8L3N0cmluZz4KCQk8aW50ZWdlcj4xMjwv + aW50ZWdlcj4KCQk8cmVhbD4zMi41PC9yZWFsPgoJCTxhcnJheT4KCQkJPGlu + dGVnZXI+MTwvaW50ZWdlcj4KCQkJPGludGVnZXI+MjwvaW50ZWdlcj4KCQkJ + PGludGVnZXI+MzwvaW50ZWdlcj4KCQk8L2FycmF5PgoJPC9hcnJheT4KCTxr + ZXk+YU5lZ2F0aXZlQmlnSW50PC9rZXk+Cgk8aW50ZWdlcj4tODAwMDAwMDAw + MDA8L2ludGVnZXI+Cgk8a2V5PmFOZWdhdGl2ZUludDwva2V5PgoJPGludGVn + ZXI+LTU8L2ludGVnZXI+Cgk8a2V5PmFTdHJpbmc8L2tleT4KCTxzdHJpbmc+ + RG9vZGFoPC9zdHJpbmc+Cgk8a2V5PmFuRW1wdHlEaWN0PC9rZXk+Cgk8ZGlj + dC8+Cgk8a2V5PmFuRW1wdHlMaXN0PC9rZXk+Cgk8YXJyYXkvPgoJPGtleT5h + bkludDwva2V5PgoJPGludGVnZXI+NzI4PC9pbnRlZ2VyPgoJPGtleT5uZXN0 + ZWREYXRhPC9rZXk+Cgk8YXJyYXk+CgkJPGRhdGE+CgkJUEd4dmRITWdiMlln WW1sdVlYSjVJR2QxYm1zK0FBRUNBenhzYjNSeklHOW1JR0pwYm1GeWVTQm5k - VzVyUGdBQkFnTTgKCWJHOTBjeUJ2WmlCaWFXNWhjbmtnWjNWdWF6NEFBUUlE - UEd4dmRITWdiMllnWW1sdVlYSjVJR2QxYm1zK0FBRUNBenhzCgliM1J6SUc5 - bUlHSnBibUZ5ZVNCbmRXNXJQZ0FCQWdNOGJHOTBjeUJ2WmlCaWFXNWhjbmtn - WjNWdWF6NEFBUUlEUEd4dgoJZEhNZ2IyWWdZbWx1WVhKNUlHZDFibXMrQUFF - Q0F6eHNiM1J6SUc5bUlHSnBibUZ5ZVNCbmRXNXJQZ0FCQWdNOGJHOTAKCWN5 - QnZaaUJpYVc1aGNua2daM1Z1YXo0QUFRSURQR3h2ZEhNZ2IyWWdZbWx1WVhK - NUlHZDFibXMrQUFFQ0F3PT0KCTwvZGF0YT4KCTxrZXk+w4ViZW5yYWE8L2tl - eT4KCTxzdHJpbmc+VGhhdCB3YXMgYSB1bmljb2RlIGtleS48L3N0cmluZz4K - PC9kaWN0Pgo8L3BsaXN0Pgo='''), + VzVyCgkJUGdBQkFnTThiRzkwY3lCdlppQmlhVzVoY25rZ1ozVnVhejRBQVFJ + RFBHeHZkSE1nYjJZZ1ltbHVZWEo1CgkJSUdkMWJtcytBQUVDQXp4c2IzUnpJ + RzltSUdKcGJtRnllU0JuZFc1clBnQUJBZ004Ykc5MGN5QnZaaUJpCgkJYVc1 + aGNua2daM1Z1YXo0QUFRSURQR3h2ZEhNZ2IyWWdZbWx1WVhKNUlHZDFibXMr + QUFFQ0F6eHNiM1J6CgkJSUc5bUlHSnBibUZ5ZVNCbmRXNXJQZ0FCQWdNOGJH + OTBjeUJ2WmlCaWFXNWhjbmtnWjNWdWF6NEFBUUlECgkJUEd4dmRITWdiMlln + WW1sdVlYSjVJR2QxYm1zK0FBRUNBdz09CgkJPC9kYXRhPgoJPC9hcnJheT4K + CTxrZXk+c29tZURhdGE8L2tleT4KCTxkYXRhPgoJUEdKcGJtRnllU0JuZFc1 + clBnPT0KCTwvZGF0YT4KCTxrZXk+c29tZU1vcmVEYXRhPC9rZXk+Cgk8ZGF0 + YT4KCVBHeHZkSE1nYjJZZ1ltbHVZWEo1SUdkMWJtcytBQUVDQXp4c2IzUnpJ + RzltSUdKcGJtRnllU0JuZFc1clBnQUJBZ004CgliRzkwY3lCdlppQmlhVzVo + Y25rZ1ozVnVhejRBQVFJRFBHeHZkSE1nYjJZZ1ltbHVZWEo1SUdkMWJtcytB + QUVDQXp4cwoJYjNSeklHOW1JR0pwYm1GeWVTQm5kVzVyUGdBQkFnTThiRzkw + Y3lCdlppQmlhVzVoY25rZ1ozVnVhejRBQVFJRFBHeHYKCWRITWdiMllnWW1s + dVlYSjVJR2QxYm1zK0FBRUNBenhzYjNSeklHOW1JR0pwYm1GeWVTQm5kVzVy + UGdBQkFnTThiRzkwCgljeUJ2WmlCaWFXNWhjbmtnWjNWdWF6NEFBUUlEUEd4 + dmRITWdiMllnWW1sdVlYSjVJR2QxYm1zK0FBRUNBdz09Cgk8L2RhdGE+Cgk8 + a2V5PsOFYmVucmFhPC9rZXk+Cgk8c3RyaW5nPlRoYXQgd2FzIGEgdW5pY29k + ZSBrZXkuPC9zdHJpbmc+CjwvZGljdD4KPC9wbGlzdD4K'''), plistlib.FMT_BINARY: binascii.a2b_base64(b''' - YnBsaXN0MDDfEA8BAgMEBQYHCAkKCwwNDg8QERImJy0uLzAxMjM1NDZXYUJp - Z0ludFVhRGF0ZVVhRGljdFZhRmxvYXRVYUxpc3RfEA9hTmVnYXRpdmVCaWdJ - bnRcYU5lZ2F0aXZlSW50V2FTdHJpbmdbYW5FbXB0eURpY3RbYW5FbXB0eUxp - c3RVYW5JbnRabmVzdGVkRGF0YVhzb21lRGF0YVxzb21lTW9yZURhdGFnAMUA - YgBlAG4AcgBhAGETf////////9QzQZy5ffQAAADVExQVFhcYGRobHFthRmFs - c2VWYWx1ZVphVHJ1ZVZhbHVlXWFVbmljb2RlVmFsdWVdYW5vdGhlclN0cmlu - Z1pkZWVwZXJEaWN0CAlrAE0A5ABzAHMAaQBnACwAIABNAGEA318QFTxoZWxs - byAmICdoaScgdGhlcmUhPtMdHh8gISJRYVFiUWMQESNAQEAAAAAAAKMjJCUQ - ARACVHRleHQjP+AAAAAAAAClKCkqIStRQVFCEAyjIyQsEAMT////7V+g4AAT - //////////tWRG9vZGFo0KARAtihNE8Q+jxsb3RzIG9mIGJpbmFyeSBndW5r - PgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5 - IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBi - aW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3Rz - IG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQID - PGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5r - PgABAgNNPGJpbmFyeSBndW5rPl8QF1RoYXQgd2FzIGEgdW5pY29kZSBrZXku - AAgAKQAxADcAPQBEAEoAXABpAHEAfQCJAI8AmgCjALAAvwDIANEA3ADoAPMB - AQEPARoBGwEcATMBSwFSAVQBVgFYAVoBYwFnAWkBawFwAXkBfwGBAYMBhQGJ - AYsBlAGdAaQBpQGmAakBqwKoArYAAAAAAAACAQAAAAAAAAA3AAAAAAAAAAAA - AAAAAAAC0A=='''), + YnBsaXN0MDDfEBABAgMEBQYHCAkKCwwNDg8QERITFCgpLzAxMjM0NTc2OFdh + QmlnSW50WGFCaWdJbnQyVWFEYXRlVWFEaWN0VmFGbG9hdFVhTGlzdF8QD2FO + ZWdhdGl2ZUJpZ0ludFxhTmVnYXRpdmVJbnRXYVN0cmluZ1thbkVtcHR5RGlj + dFthbkVtcHR5TGlzdFVhbkludFpuZXN0ZWREYXRhWHNvbWVEYXRhXHNvbWVN + b3JlRGF0YWcAxQBiAGUAbgByAGEAYRN/////////1BQAAAAAAAAAAIAAAAAA + AAAsM0GcuX30AAAA1RUWFxgZGhscHR5bYUZhbHNlVmFsdWVaYVRydWVWYWx1 + ZV1hVW5pY29kZVZhbHVlXWFub3RoZXJTdHJpbmdaZGVlcGVyRGljdAgJawBN + AOQAcwBzAGkAZwAsACAATQBhAN9fEBU8aGVsbG8gJiAnaGknIHRoZXJlIT7T + HyAhIiMkUWFRYlFjEBEjQEBAAAAAAACjJSYnEAEQAlR0ZXh0Iz/gAAAAAAAA + pSorLCMtUUFRQhAMoyUmLhADE////+1foOAAE//////////7VkRvb2RhaNCg + EQLYoTZPEPo8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmlu + YXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBv + ZiBiaW5hcnkgZ3Vuaz4AAQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxs + b3RzIG9mIGJpbmFyeSBndW5rPgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4A + AQIDPGxvdHMgb2YgYmluYXJ5IGd1bms+AAECAzxsb3RzIG9mIGJpbmFyeSBn + dW5rPgABAgM8bG90cyBvZiBiaW5hcnkgZ3Vuaz4AAQIDTTxiaW5hcnkgZ3Vu + az5fEBdUaGF0IHdhcyBhIHVuaWNvZGUga2V5LgAIACsAMwA8AEIASABPAFUA + ZwB0AHwAiACUAJoApQCuALsAygDTAOQA7QD4AQQBDwEdASsBNgE3ATgBTwFn + AW4BcAFyAXQBdgF/AYMBhQGHAYwBlQGbAZ0BnwGhAaUBpwGwAbkBwAHBAcIB + xQHHAsQC0gAAAAAAAAIBAAAAAAAAADkAAAAAAAAAAAAAAAAAAALs'''), } @@ -106,6 +107,7 @@ aFloat = 0.5, anInt = 728, aBigInt = 2 ** 63 - 44, + aBigInt2 = 2 ** 63 + 44, aNegativeInt = -5, aNegativeBigInt = -80000000000, aDict=dict( @@ -152,7 +154,7 @@ def test_int(self): for pl in [0, 2**8-1, 2**8, 2**16-1, 2**16, 2**32-1, 2**32, - 2**63-1, 1, -2**63]: + 2**63-1, 2**64-1, 1, -2**63]: for fmt in ALL_FORMATS: with self.subTest(pl=pl, fmt=fmt): data = plistlib.dumps(pl, fmt=fmt) diff --git a/Mac/Tools/plistlib_generate_testdata.py b/Mac/Tools/plistlib_generate_testdata.py --- a/Mac/Tools/plistlib_generate_testdata.py +++ b/Mac/Tools/plistlib_generate_testdata.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -from Cocoa import NSMutableDictionary, NSMutableArray, NSString, NSDate +from Cocoa import NSMutableDictionary, NSMutableArray, NSString, NSDate, NSNumber from Cocoa import NSPropertyListSerialization, NSPropertyListOpenStepFormat from Cocoa import NSPropertyListXMLFormat_v1_0, NSPropertyListBinaryFormat_v1_0 from Cocoa import CFUUIDCreateFromString, NSNull, NSUUID, CFPropertyListCreateData @@ -30,6 +30,7 @@ seconds = datetime.datetime(2004, 10, 26, 10, 33, 33, tzinfo=datetime.timezone(datetime.timedelta(0))).timestamp() pl[nsstr('aBigInt')] = 2 ** 63 - 44 + pl[nsstr('aBigInt2')] = NSNumber.numberWithUnsignedLongLong_(2 ** 63 + 44) pl[nsstr('aDate')] = NSDate.dateWithTimeIntervalSince1970_(seconds) pl[nsstr('aDict')] = d = OrderedDict() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -109,6 +109,10 @@ - Issue #15304: concurrent.futures.wait() can block forever even if Futures have completed. Patch by Glenn Langford. +- Issue #14455: plistlib: fix serializing integers integers in the range + of an unsigned long long but outside of the range of signed long long for + binary plist files. + IDLE ---- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 15:23:03 2014 From: python-checkins at python.org (brett.cannon) Date: Thu, 6 Feb 2014 15:23:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=236386=3A_When_exec?= =?utf-8?q?uting_a_script_that=27s_a_symlink=2C_the_directory?= Message-ID: <3fKhgq4cq8z7M0b@mail.python.org> http://hg.python.org/cpython/rev/47c31e7d3779 changeset: 88992:47c31e7d3779 user: Brett Cannon date: Thu Feb 06 09:22:51 2014 -0500 summary: Issue #6386: When executing a script that's a symlink, the directory where the symlink resolves to is added to sys.path, not the directory containing the symlink itself. Thanks to Sanko Resic for an initial attempt at the patch. files: Doc/tutorial/modules.rst | 10 ++++++++-- Misc/NEWS | 7 +++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Doc/tutorial/modules.rst b/Doc/tutorial/modules.rst --- a/Doc/tutorial/modules.rst +++ b/Doc/tutorial/modules.rst @@ -165,10 +165,16 @@ named :file:`spam.py` in a list of directories given by the variable :data:`sys.path`. :data:`sys.path` is initialized from these locations: -* the directory containing the input script (or the current directory). +* The directory containing the input script (or the current directory when no + file is specified). * :envvar:`PYTHONPATH` (a list of directory names, with the same syntax as the shell variable :envvar:`PATH`). -* the installation-dependent default. +* The installation-dependent default. + +.. note:: + On file systems which support symlinks, the directory containing the input + script is calculated after the symlink is followed. In other words the + directory containing the symlink is **not** added to the module search path. After initialization, Python programs can modify :data:`sys.path`. The directory containing the script being run is placed at the beginning of the diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -163,6 +163,13 @@ - Issue #20465: Update SQLite shipped with OS X installer to 3.8.3. +Documentation +------------- + +- Issue #6386: Clarify in the tutorial that specifying a symlink to execute + means the directory containing the executed script and not the symlink is + added to sys.path. + What's New in Python 3.4.0 Beta 3? ================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 15:50:07 2014 From: python-checkins at python.org (brett.cannon) Date: Thu, 6 Feb 2014 15:50:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNDg4?= =?utf-8?q?=3A_Update_docs_to_say_importlib_is_*the*_implementaiton_of?= Message-ID: <3fKjH30rG5z7Lk2@mail.python.org> http://hg.python.org/cpython/rev/cc08bf665dea changeset: 88993:cc08bf665dea branch: 3.3 parent: 88989:82d374a9bbc7 user: Brett Cannon date: Thu Feb 06 09:46:08 2014 -0500 summary: Issue #20488: Update docs to say importlib is *the* implementaiton of import and not *an* implementation. files: Doc/library/importlib.rst | 14 ++++++++------ Misc/NEWS | 3 +++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -1,8 +1,8 @@ -:mod:`importlib` -- An implementation of :keyword:`import` -========================================================== +:mod:`importlib` -- The implementation of :keyword:`import` +=========================================================== .. module:: importlib - :synopsis: An implementation of the import machinery. + :synopsis: The implementation of the import machinery. .. moduleauthor:: Brett Cannon .. sectionauthor:: Brett Cannon @@ -13,17 +13,16 @@ Introduction ------------ -The purpose of the :mod:`importlib` package is two-fold. One is to provide an +The purpose of the :mod:`importlib` package is two-fold. One is to provide the implementation of the :keyword:`import` statement (and thus, by extension, the :func:`__import__` function) in Python source code. This provides an implementation of :keyword:`import` which is portable to any Python -interpreter. This also provides a reference implementation which is easier to +interpreter. This also provides an implementation which is easier to comprehend than one implemented in a programming language other than Python. Two, the components to implement :keyword:`import` are exposed in this package, making it easier for users to create their own custom objects (known generically as an :term:`importer`) to participate in the import process. -Details on custom importers can be found in :pep:`302`. .. seealso:: @@ -53,6 +52,9 @@ :pep:`366` Main module explicit relative imports + :pep:`451` + A ModuleSpec Type for the Import System + :pep:`3120` Using UTF-8 as the Default Source Encoding diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -379,6 +379,9 @@ Documentation ------------- +- Issue #20488: Importlib is no longer *an* implementation of import, it's *the* + implementation. + - Issue #20265: Updated some parts of the Using Windows document. - Issue #20266: Updated some parts of the Windows FAQ. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 15:50:08 2014 From: python-checkins at python.org (brett.cannon) Date: Thu, 6 Feb 2014 15:50:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_for_issue_=2320488?= Message-ID: <3fKjH42y2wz7LjW@mail.python.org> http://hg.python.org/cpython/rev/5641c0b50072 changeset: 88994:5641c0b50072 parent: 88992:47c31e7d3779 parent: 88993:cc08bf665dea user: Brett Cannon date: Thu Feb 06 09:49:53 2014 -0500 summary: Merge for issue #20488 files: Doc/library/importlib.rst | 14 ++++++++------ Misc/NEWS | 3 +++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -1,8 +1,8 @@ -:mod:`importlib` -- An implementation of :keyword:`import` -========================================================== +:mod:`importlib` -- The implementation of :keyword:`import` +=========================================================== .. module:: importlib - :synopsis: An implementation of the import machinery. + :synopsis: The implementation of the import machinery. .. moduleauthor:: Brett Cannon .. sectionauthor:: Brett Cannon @@ -13,17 +13,16 @@ Introduction ------------ -The purpose of the :mod:`importlib` package is two-fold. One is to provide an +The purpose of the :mod:`importlib` package is two-fold. One is to provide the implementation of the :keyword:`import` statement (and thus, by extension, the :func:`__import__` function) in Python source code. This provides an implementation of :keyword:`import` which is portable to any Python -interpreter. This also provides a reference implementation which is easier to +interpreter. This also provides an implementation which is easier to comprehend than one implemented in a programming language other than Python. Two, the components to implement :keyword:`import` are exposed in this package, making it easier for users to create their own custom objects (known generically as an :term:`importer`) to participate in the import process. -Details on custom importers can be found in :pep:`302`. .. seealso:: @@ -53,6 +52,9 @@ :pep:`366` Main module explicit relative imports + :pep:`451` + A ModuleSpec Type for the Import System + :pep:`3120` Using UTF-8 as the Default Source Encoding diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -166,6 +166,9 @@ Documentation ------------- +- Issue #20488: Change wording to say importlib is *the* implementation of + import instead of just *an* implementation. + - Issue #6386: Clarify in the tutorial that specifying a symlink to execute means the directory containing the executed script and not the symlink is added to sys.path. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 17:13:13 2014 From: python-checkins at python.org (ethan.furman) Date: Thu, 6 Feb 2014 17:13:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_issue20412=3A_Update?= =?utf-8?q?d_Enum_docs_to_have_referencable_Enum_and_IntEnum?= Message-ID: <3fKl6x1ypqz7LjW@mail.python.org> http://hg.python.org/cpython/rev/eeb582c0c014 changeset: 88995:eeb582c0c014 user: Ethan Furman date: Thu Feb 06 08:13:14 2014 -0800 summary: Close issue20412: Updated Enum docs to have referencable Enum and IntEnum classes files: Doc/library/enum.rst | 27 ++++++++++++++++++++++----- 1 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -15,14 +15,31 @@ ---------------- -An enumeration is a set of symbolic names (members) bound to unique, constant -values. Within an enumeration, the members can be compared by identity, and -the enumeration itself can be iterated over. +An enumeration is a set of symbolic names (members) bound to unique, +constant values. Within an enumeration, the members can be compared +by identity, and the enumeration itself can be iterated over. + + +Module Contents +--------------- This module defines two enumeration classes that can be used to define unique sets of names and values: :class:`Enum` and :class:`IntEnum`. It also defines -one decorator, :func:`unique`, that ensures only unique member values are -present in an enumeration. +one decorator, :func:`unique`. + +.. class:: Enum + + Base class for creating enumerated constants. See section + :ref:`Functional API` for an alternate construction syntax. + +.. class:: IntEnum + + Base class for creating enumerated constants that are also + subclasses of :class:`int`. + +.. function:: unique + + Enum class decorator that ensures only one name is bound to any one value. Creating an Enum -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 18:04:02 2014 From: python-checkins at python.org (yury.selivanov) Date: Thu, 6 Feb 2014 18:04:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Etasks=2Egather?= =?utf-8?q?=3A_Fix_docstring?= Message-ID: <3fKmFZ2xLhz7LjM@mail.python.org> http://hg.python.org/cpython/rev/a46862fc4d18 changeset: 88996:a46862fc4d18 user: Yury Selivanov date: Thu Feb 06 12:03:53 2014 -0500 summary: asyncio.tasks.gather: Fix docstring files: Lib/asyncio/tasks.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -555,7 +555,7 @@ All futures must share the same event loop. If all the tasks are done successfully, the returned future's result is the list of results (in the order of the original sequence, not necessarily - the order of results arrival). If *result_exception* is True, + the order of results arrival). If *return_exceptions* is True, exceptions in the tasks are treated the same as successful results, and gathered in the result list; otherwise, the first raised exception will be immediately propagated to the returned -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 20:13:55 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 6 Feb 2014 20:13:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Fix_empty_stri?= =?utf-8?q?ngs_to_empty_bytes_objects=2E?= Message-ID: <3fKq7R3rgnz7Lk2@mail.python.org> http://hg.python.org/cpython/rev/733e19123915 changeset: 88997:733e19123915 branch: 3.3 parent: 88993:cc08bf665dea user: Serhiy Storchaka date: Thu Feb 06 21:10:41 2014 +0200 summary: Fix empty strings to empty bytes objects. files: Doc/library/asynchat.rst | 6 +++--- Doc/library/asyncore.rst | 3 ++- Doc/library/chunk.rst | 8 ++++---- Doc/library/xml.etree.elementtree.rst | 2 +- Doc/library/zlib.rst | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Doc/library/asynchat.rst b/Doc/library/asynchat.rst --- a/Doc/library/asynchat.rst +++ b/Doc/library/asynchat.rst @@ -56,8 +56,8 @@ have only one method, :meth:`more`, which should return data to be transmitted on the channel. The producer indicates exhaustion (*i.e.* that it contains no more data) by - having its :meth:`more` method return the empty string. At this point the - :class:`async_chat` object removes the producer from the fifo and starts + having its :meth:`more` method return the empty bytes object. At this point + the :class:`async_chat` object removes the producer from the fifo and starts using the next producer, if any. When the producer fifo is empty the :meth:`handle_write` method does nothing. You use the channel object's :meth:`set_terminator` method to describe how to recognize the end of, or @@ -221,7 +221,7 @@ def found_terminator(self): if self.reading_headers: self.reading_headers = False - self.parse_headers("".join(self.ibuffer)) + self.parse_headers(b"".join(self.ibuffer)) self.ibuffer = [] if self.op.upper() == b"POST": clen = self.headers.getheader("content-length") diff --git a/Doc/library/asyncore.rst b/Doc/library/asyncore.rst --- a/Doc/library/asyncore.rst +++ b/Doc/library/asyncore.rst @@ -208,7 +208,8 @@ .. method:: recv(buffer_size) Read at most *buffer_size* bytes from the socket's remote end-point. An - empty string implies that the channel has been closed from the other end. + empty bytes object implies that the channel has been closed from the + other end. .. method:: listen(backlog) diff --git a/Doc/library/chunk.rst b/Doc/library/chunk.rst --- a/Doc/library/chunk.rst +++ b/Doc/library/chunk.rst @@ -113,15 +113,15 @@ Read at most *size* bytes from the chunk (less if the read hits the end of the chunk before obtaining *size* bytes). If the *size* argument is - negative or omitted, read all data until the end of the chunk. The bytes - are returned as a string object. An empty string is returned when the end - of the chunk is encountered immediately. + negative or omitted, read all data until the end of the chunk. An empty + bytes object is returned when the end of the chunk is encountered + immediately. .. method:: skip() Skip to the end of the chunk. All further calls to :meth:`read` for the - chunk will return ``''``. If you are not interested in the contents of + chunk will return ``b''``. If you are not interested in the contents of the chunk, this method should be called so that the file points to the start of the next chunk. diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -457,7 +457,7 @@ is either ``"xml"``, ``"html"`` or ``"text"`` (default is ``"xml"``). Returns a list of (optionally) encoded strings containing the XML data. It does not guarantee any specific sequence, except that - ``"".join(tostringlist(element)) == tostring(element)``. + ``b"".join(tostringlist(element)) == tostring(element)``. .. versionadded:: 3.2 diff --git a/Doc/library/zlib.rst b/Doc/library/zlib.rst --- a/Doc/library/zlib.rst +++ b/Doc/library/zlib.rst @@ -197,7 +197,7 @@ .. attribute:: Decompress.unused_data A bytes object which contains any bytes past the end of the compressed data. That is, - this remains ``""`` until the last byte that contains compression data is + this remains ``b""`` until the last byte that contains compression data is available. If the whole bytestring turned out to contain compressed data, this is ``b""``, an empty bytes object. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 20:13:56 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 6 Feb 2014 20:13:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Fix_empty_strings_to_empty_bytes_objects=2E?= Message-ID: <3fKq7S6jHjz7LlL@mail.python.org> http://hg.python.org/cpython/rev/50d18b5ac776 changeset: 88998:50d18b5ac776 parent: 88996:a46862fc4d18 parent: 88997:733e19123915 user: Serhiy Storchaka date: Thu Feb 06 21:11:33 2014 +0200 summary: Fix empty strings to empty bytes objects. files: Doc/library/asynchat.rst | 6 +++--- Doc/library/asyncore.rst | 3 ++- Doc/library/chunk.rst | 8 ++++---- Doc/library/xml.etree.elementtree.rst | 2 +- Doc/library/zlib.rst | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Doc/library/asynchat.rst b/Doc/library/asynchat.rst --- a/Doc/library/asynchat.rst +++ b/Doc/library/asynchat.rst @@ -61,8 +61,8 @@ have only one method, :meth:`more`, which should return data to be transmitted on the channel. The producer indicates exhaustion (*i.e.* that it contains no more data) by - having its :meth:`more` method return the empty string. At this point the - :class:`async_chat` object removes the producer from the fifo and starts + having its :meth:`more` method return the empty bytes object. At this point + the :class:`async_chat` object removes the producer from the fifo and starts using the next producer, if any. When the producer fifo is empty the :meth:`handle_write` method does nothing. You use the channel object's :meth:`set_terminator` method to describe how to recognize the end of, or @@ -226,7 +226,7 @@ def found_terminator(self): if self.reading_headers: self.reading_headers = False - self.parse_headers("".join(self.ibuffer)) + self.parse_headers(b"".join(self.ibuffer)) self.ibuffer = [] if self.op.upper() == b"POST": clen = self.headers.getheader("content-length") diff --git a/Doc/library/asyncore.rst b/Doc/library/asyncore.rst --- a/Doc/library/asyncore.rst +++ b/Doc/library/asyncore.rst @@ -213,7 +213,8 @@ .. method:: recv(buffer_size) Read at most *buffer_size* bytes from the socket's remote end-point. An - empty string implies that the channel has been closed from the other end. + empty bytes object implies that the channel has been closed from the + other end. .. method:: listen(backlog) diff --git a/Doc/library/chunk.rst b/Doc/library/chunk.rst --- a/Doc/library/chunk.rst +++ b/Doc/library/chunk.rst @@ -113,15 +113,15 @@ Read at most *size* bytes from the chunk (less if the read hits the end of the chunk before obtaining *size* bytes). If the *size* argument is - negative or omitted, read all data until the end of the chunk. The bytes - are returned as a string object. An empty string is returned when the end - of the chunk is encountered immediately. + negative or omitted, read all data until the end of the chunk. An empty + bytes object is returned when the end of the chunk is encountered + immediately. .. method:: skip() Skip to the end of the chunk. All further calls to :meth:`read` for the - chunk will return ``''``. If you are not interested in the contents of + chunk will return ``b''``. If you are not interested in the contents of the chunk, this method should be called so that the file points to the start of the next chunk. diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -511,7 +511,7 @@ *short_empty_elements* has the same meaning as in :meth:`ElementTree.write`. Returns a list of (optionally) encoded strings containing the XML data. It does not guarantee any specific sequence, except that - ``"".join(tostringlist(element)) == tostring(element)``. + ``b"".join(tostringlist(element)) == tostring(element)``. .. versionadded:: 3.2 diff --git a/Doc/library/zlib.rst b/Doc/library/zlib.rst --- a/Doc/library/zlib.rst +++ b/Doc/library/zlib.rst @@ -197,7 +197,7 @@ .. attribute:: Decompress.unused_data A bytes object which contains any bytes past the end of the compressed data. That is, - this remains ``""`` until the last byte that contains compression data is + this remains ``b""`` until the last byte that contains compression data is available. If the whole bytestring turned out to contain compressed data, this is ``b""``, an empty bytes object. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 21:57:15 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 6 Feb 2014 21:57:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Catch_deprecation_warnings?= =?utf-8?q?_emitted_when_non-integers_are_formatted_with_=25c=2C_=25o?= Message-ID: <3fKsQg35HYz7Lkh@mail.python.org> http://hg.python.org/cpython/rev/775fb736b4b8 changeset: 88999:775fb736b4b8 user: Serhiy Storchaka date: Thu Feb 06 22:44:27 2014 +0200 summary: Catch deprecation warnings emitted when non-integers are formatted with %c, %o and %x (introduced in issue #19995). files: Lib/test/string_tests.py | 3 ++- Lib/test/test_format.py | 15 ++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -1179,7 +1179,8 @@ self.checkraises(TypeError, 'abc', '__mod__') self.checkraises(TypeError, '%(foo)s', '__mod__', 42) self.checkraises(TypeError, '%s%s', '__mod__', (42,)) - self.checkraises(TypeError, '%c', '__mod__', (None,)) + with self.assertWarns(DeprecationWarning): + self.checkraises(TypeError, '%c', '__mod__', (None,)) self.checkraises(ValueError, '%(foo', '__mod__', {}) self.checkraises(TypeError, '%(foo)s %(bar)s', '__mod__', ('foo', 42)) self.checkraises(TypeError, '%d', '__mod__', "42") # not numeric diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -142,7 +142,8 @@ testformat("%#+027.23X", big, "+0X0001234567890ABCDEF12345") # same, except no 0 flag testformat("%#+27.23X", big, " +0X001234567890ABCDEF12345") - testformat("%x", float(big), "123456_______________", 6) + with self.assertWarns(DeprecationWarning): + testformat("%x", float(big), "123456_______________", 6) big = 0o12345670123456701234567012345670 # 32 octal digits testformat("%o", big, "12345670123456701234567012345670") testformat("%o", -big, "-12345670123456701234567012345670") @@ -182,7 +183,8 @@ testformat("%034.33o", big, "0012345670123456701234567012345670") # base marker shouldn't change that testformat("%0#34.33o", big, "0o012345670123456701234567012345670") - testformat("%o", float(big), "123456__________________________", 6) + with self.assertWarns(DeprecationWarning): + testformat("%o", float(big), "123456__________________________", 6) # Some small ints, in both Python int and flavors). testformat("%d", 42, "42") testformat("%d", -42, "-42") @@ -193,7 +195,8 @@ testformat("%#x", 1, "0x1") testformat("%#X", 1, "0X1") testformat("%#X", 1, "0X1") - testformat("%#x", 1.0, "0x1") + with self.assertWarns(DeprecationWarning): + testformat("%#x", 1.0, "0x1") testformat("%#o", 1, "0o1") testformat("%#o", 1, "0o1") testformat("%#o", 0, "0o0") @@ -210,12 +213,14 @@ testformat("%x", -0x42, "-42") testformat("%x", 0x42, "42") testformat("%x", -0x42, "-42") - testformat("%x", float(0x42), "42") + with self.assertWarns(DeprecationWarning): + testformat("%x", float(0x42), "42") testformat("%o", 0o42, "42") testformat("%o", -0o42, "-42") testformat("%o", 0o42, "42") testformat("%o", -0o42, "-42") - testformat("%o", float(0o42), "42") + with self.assertWarns(DeprecationWarning): + testformat("%o", float(0o42), "42") testformat("%r", "\u0378", "'\\u0378'") # non printable testformat("%a", "\u0378", "'\\u0378'") # non printable testformat("%r", "\u0374", "'\u0374'") # printable -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 21:57:16 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 6 Feb 2014 21:57:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwMzYz?= =?utf-8?q?=2E_Fixed_BytesWarning_triggerred_by_test_suite=2E?= Message-ID: <3fKsQh5vJCz7LlB@mail.python.org> http://hg.python.org/cpython/rev/791674a74e47 changeset: 89000:791674a74e47 branch: 3.3 parent: 88997:733e19123915 user: Serhiy Storchaka date: Thu Feb 06 22:49:45 2014 +0200 summary: Issue #20363. Fixed BytesWarning triggerred by test suite. Patch by Berker Peksag. files: Lib/configparser.py | 4 ++-- Lib/distutils/command/register.py | 2 +- Lib/test/test_hash.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/configparser.py b/Lib/configparser.py --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -286,7 +286,7 @@ raise ValueError("Required argument `source' not given.") elif filename: source = filename - Error.__init__(self, 'Source contains parsing errors: %s' % source) + Error.__init__(self, 'Source contains parsing errors: %r' % source) self.source = source self.errors = [] self.args = (source, ) @@ -322,7 +322,7 @@ def __init__(self, filename, lineno, line): Error.__init__( self, - 'File contains no section headers.\nfile: %s, line: %d\n%r' % + 'File contains no section headers.\nfile: %r, line: %d\n%r' % (filename, lineno, line)) self.source = filename self.lineno = lineno diff --git a/Lib/distutils/command/register.py b/Lib/distutils/command/register.py --- a/Lib/distutils/command/register.py +++ b/Lib/distutils/command/register.py @@ -300,5 +300,5 @@ result = 200, 'OK' if self.show_response: dashes = '-' * 75 - self.announce('%s%s%s' % (dashes, data, dashes)) + self.announce('%s%r%s' % (dashes, data, dashes)) return result diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -138,7 +138,7 @@ # an object to be tested def get_hash_command(self, repr_): - return 'print(hash(%s))' % repr_ + return 'print(hash(eval(%a)))' % repr_ def get_hash(self, repr_, seed=None): env = os.environ.copy() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 21:57:18 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 6 Feb 2014 21:57:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320363=2E_Fixed_BytesWarning_triggerred_by_test_?= =?utf-8?q?suite=2E?= Message-ID: <3fKsQk0dxrz7Lk4@mail.python.org> http://hg.python.org/cpython/rev/a4431dce107a changeset: 89001:a4431dce107a parent: 88999:775fb736b4b8 parent: 89000:791674a74e47 user: Serhiy Storchaka date: Thu Feb 06 22:52:23 2014 +0200 summary: Issue #20363. Fixed BytesWarning triggerred by test suite. Patch by Berker Peksag. files: Lib/base64.py | 2 +- Lib/configparser.py | 4 ++-- Lib/distutils/command/register.py | 2 +- Lib/test/test_hash.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/base64.py b/Lib/base64.py --- a/Lib/base64.py +++ b/Lib/base64.py @@ -362,7 +362,7 @@ if adobe: if not (b.startswith(_A85START) and b.endswith(_A85END)): raise ValueError("Ascii85 encoded byte sequences must be bracketed " - "by {} and {}".format(_A85START, _A85END)) + "by {!r} and {!r}".format(_A85START, _A85END)) b = b[2:-2] # Strip off start/end markers # # We have to go through this stepwise, so as to ignore spaces and handle diff --git a/Lib/configparser.py b/Lib/configparser.py --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -286,7 +286,7 @@ raise ValueError("Required argument `source' not given.") elif filename: source = filename - Error.__init__(self, 'Source contains parsing errors: %s' % source) + Error.__init__(self, 'Source contains parsing errors: %r' % source) self.source = source self.errors = [] self.args = (source, ) @@ -322,7 +322,7 @@ def __init__(self, filename, lineno, line): Error.__init__( self, - 'File contains no section headers.\nfile: %s, line: %d\n%r' % + 'File contains no section headers.\nfile: %r, line: %d\n%r' % (filename, lineno, line)) self.source = filename self.lineno = lineno diff --git a/Lib/distutils/command/register.py b/Lib/distutils/command/register.py --- a/Lib/distutils/command/register.py +++ b/Lib/distutils/command/register.py @@ -300,5 +300,5 @@ result = 200, 'OK' if self.show_response: dashes = '-' * 75 - self.announce('%s%s%s' % (dashes, data, dashes)) + self.announce('%s%r%s' % (dashes, data, dashes)) return result diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -172,7 +172,7 @@ # an object to be tested def get_hash_command(self, repr_): - return 'print(hash(eval(%r.decode("utf-8"))))' % repr_.encode("utf-8") + return 'print(hash(eval(%a)))' % repr_ def get_hash(self, repr_, seed=None): env = os.environ.copy() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 22:47:09 2014 From: python-checkins at python.org (zach.ware) Date: Thu, 6 Feb 2014 22:47:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=233158=3A_Provide_a?= =?utf-8?q?_couple_of_fallbacks_for_in_case_a_method=5Fdescriptor?= Message-ID: <3fKtXF0qvvzMrl@mail.python.org> http://hg.python.org/cpython/rev/c964b6b83720 changeset: 89002:c964b6b83720 user: Zachary Ware date: Thu Feb 06 15:46:38 2014 -0600 summary: Issue #3158: Provide a couple of fallbacks for in case a method_descriptor doesn't have __objclass__. files: Lib/doctest.py | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Lib/doctest.py b/Lib/doctest.py --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -945,7 +945,13 @@ elif inspect.isfunction(object): return module.__dict__ is object.__globals__ elif inspect.ismethoddescriptor(object): - return module.__name__ == object.__objclass__.__module__ + if hasattr(object, '__objclass__'): + obj_mod = object.__objclass__.__module__ + elif hasattr(object, '__module__'): + obj_mod = object.__module__ + else: + return True # [XX] no easy way to tell otherwise + return module.__name__ == obj_mod elif inspect.isclass(object): return module.__name__ == object.__module__ elif hasattr(object, '__module__'): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 23:29:06 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 6 Feb 2014 23:29:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Silence_BytesW?= =?utf-8?q?arning_=28backport_267a4d4d9d65=29=2E?= Message-ID: <3fKvSf5kCWz7Lkk@mail.python.org> http://hg.python.org/cpython/rev/98d9d152e94b changeset: 89003:98d9d152e94b branch: 3.3 parent: 89000:791674a74e47 user: Serhiy Storchaka date: Fri Feb 07 00:26:57 2014 +0200 summary: Silence BytesWarning (backport 267a4d4d9d65). files: Lib/test/test_exceptions.py | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -8,8 +8,8 @@ import errno from test.support import (TESTFN, captured_output, check_impl_detail, - cpython_only, gc_collect, run_unittest, no_tracing, - unlink) + check_warnings, cpython_only, gc_collect, + no_tracing, run_unittest, unlink) class NaiveException(Exception): def __init__(self, x): @@ -960,9 +960,10 @@ def test_non_str_argument(self): # Issue #15778 - arg = b'abc' - exc = ImportError(arg) - self.assertEqual(str(arg), str(exc)) + with check_warnings(('', BytesWarning), quiet=True): + arg = b'abc' + exc = ImportError(arg) + self.assertEqual(str(arg), str(exc)) def test_main(): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 6 23:29:08 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 6 Feb 2014 23:29:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <3fKvSh0211z7Lkx@mail.python.org> http://hg.python.org/cpython/rev/0f313b285970 changeset: 89004:0f313b285970 parent: 89002:c964b6b83720 parent: 89003:98d9d152e94b user: Serhiy Storchaka date: Fri Feb 07 00:29:03 2014 +0200 summary: Null merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 02:28:47 2014 From: python-checkins at python.org (ethan.furman) Date: Fri, 7 Feb 2014 02:28:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_issue20534=3A_test?= =?utf-8?q?=5Fenum_now_tests_all_supported_pickle_protocols_=282_-?= Message-ID: <3fKzRz631sz7LjM@mail.python.org> http://hg.python.org/cpython/rev/35f57ab9389b changeset: 89005:35f57ab9389b user: Ethan Furman date: Thu Feb 06 17:28:50 2014 -0800 summary: Close issue20534: test_enum now tests all supported pickle protocols (2 - HIGHEST_PROTOCOL, inclusive). files: Lib/test/test_enum.py | 60 ++++++++++++++++++------------ 1 files changed, 36 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -5,7 +5,7 @@ from collections import OrderedDict from enum import Enum, IntEnum, EnumMeta, unique from io import StringIO -from pickle import dumps, loads, PicklingError +from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL # for pickle tests try: @@ -61,6 +61,16 @@ except Exception: pass +def test_pickle_dump_load(assertion, source, target=None): + if target is None: + target = source + for protocol in range(2, HIGHEST_PROTOCOL+1): + assertion(loads(dumps(source, protocol=protocol)), target) + +def test_pickle_exception(assertion, exception, obj): + for protocol in range(2, HIGHEST_PROTOCOL+1): + with assertion(exception): + dumps(obj, protocol=protocol) class TestHelpers(unittest.TestCase): # _is_descriptor, _is_sunder, _is_dunder @@ -503,41 +513,40 @@ def test_pickle_enum(self): if isinstance(Stooges, Exception): raise Stooges - self.assertIs(Stooges.CURLY, loads(dumps(Stooges.CURLY))) - self.assertIs(Stooges, loads(dumps(Stooges))) + test_pickle_dump_load(self.assertIs, Stooges.CURLY) + test_pickle_dump_load(self.assertIs, Stooges) def test_pickle_int(self): if isinstance(IntStooges, Exception): raise IntStooges - self.assertIs(IntStooges.CURLY, loads(dumps(IntStooges.CURLY))) - self.assertIs(IntStooges, loads(dumps(IntStooges))) + test_pickle_dump_load(self.assertIs, IntStooges.CURLY) + test_pickle_dump_load(self.assertIs, IntStooges) def test_pickle_float(self): if isinstance(FloatStooges, Exception): raise FloatStooges - self.assertIs(FloatStooges.CURLY, loads(dumps(FloatStooges.CURLY))) - self.assertIs(FloatStooges, loads(dumps(FloatStooges))) + test_pickle_dump_load(self.assertIs, FloatStooges.CURLY) + test_pickle_dump_load(self.assertIs, FloatStooges) def test_pickle_enum_function(self): if isinstance(Answer, Exception): raise Answer - self.assertIs(Answer.him, loads(dumps(Answer.him))) - self.assertIs(Answer, loads(dumps(Answer))) + test_pickle_dump_load(self.assertIs, Answer.him) + test_pickle_dump_load(self.assertIs, Answer) def test_pickle_enum_function_with_module(self): if isinstance(Question, Exception): raise Question - self.assertIs(Question.who, loads(dumps(Question.who))) - self.assertIs(Question, loads(dumps(Question))) + test_pickle_dump_load(self.assertIs, Question.who) + test_pickle_dump_load(self.assertIs, Question) def test_exploding_pickle(self): BadPickle = Enum('BadPickle', 'dill sweet bread-n-butter') - enum._make_class_unpicklable(BadPickle) + BadPickle.__qualname__ = 'BadPickle' # needed for pickle protocol 4 globals()['BadPickle'] = BadPickle - with self.assertRaises(TypeError): - dumps(BadPickle.dill) - with self.assertRaises(PicklingError): - dumps(BadPickle) + enum._make_class_unpicklable(BadPickle) # will overwrite __qualname__ + test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill) + test_pickle_exception(self.assertRaises, PicklingError, BadPickle) def test_string_enum(self): class SkillLevel(str, Enum): @@ -690,7 +699,7 @@ self.assertEqual(Name.BDFL, 'Guido van Rossum') self.assertTrue(Name.BDFL, Name('Guido van Rossum')) self.assertIs(Name.BDFL, getattr(Name, 'BDFL')) - self.assertIs(Name.BDFL, loads(dumps(Name.BDFL))) + test_pickle_dump_load(self.assertIs, Name.BDFL) def test_extending(self): class Color(Enum): @@ -864,6 +873,7 @@ def test_subclasses_with_getnewargs(self): class NamedInt(int): + __qualname__ = 'NamedInt' # needed for pickle protocol 4 def __new__(cls, *args): _args = args name, *args = args @@ -902,6 +912,7 @@ return temp class NEI(NamedInt, Enum): + __qualname__ = 'NEI' # needed for pickle protocol 4 x = ('the-x', 1) y = ('the-y', 2) @@ -912,12 +923,13 @@ globals()['NEI'] = NEI NI5 = NamedInt('test', 5) self.assertEqual(NI5, 5) - self.assertEqual(loads(dumps(NI5)), 5) + test_pickle_dump_load(self.assertEqual, NI5, 5) self.assertEqual(NEI.y.value, 2) - self.assertIs(loads(dumps(NEI.y)), NEI.y) + test_pickle_dump_load(self.assertIs, NEI.y) def test_subclasses_without_getnewargs(self): class NamedInt(int): + __qualname__ = 'NamedInt' def __new__(cls, *args): _args = args name, *args = args @@ -954,6 +966,7 @@ return temp class NEI(NamedInt, Enum): + __qualname__ = 'NEI' x = ('the-x', 1) y = ('the-y', 2) @@ -964,13 +977,12 @@ NI5 = NamedInt('test', 5) self.assertEqual(NI5, 5) self.assertEqual(NEI.y.value, 2) - with self.assertRaises(TypeError): - dumps(NEI.x) - with self.assertRaises(PicklingError): - dumps(NEI) + test_pickle_exception(self.assertRaises, TypeError, NEI.x) + test_pickle_exception(self.assertRaises, PicklingError, NEI) def test_tuple_subclass(self): class SomeTuple(tuple, Enum): + __qualname__ = 'SomeTuple' # needed for pickle protocol 4 first = (1, 'for the money') second = (2, 'for the show') third = (3, 'for the music') @@ -978,7 +990,7 @@ self.assertIsInstance(SomeTuple.second, tuple) self.assertEqual(SomeTuple.third, (3, 'for the music')) globals()['SomeTuple'] = SomeTuple - self.assertIs(loads(dumps(SomeTuple.first)), SomeTuple.first) + test_pickle_dump_load(self.assertIs, SomeTuple.first) def test_duplicate_values_give_unique_enum_items(self): class AutoNumber(Enum): -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Feb 7 04:03:33 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 07 Feb 2014 04:03:33 +0100 Subject: [Python-checkins] Daily reference leaks (35f57ab9389b): sum=4 Message-ID: results for 35f57ab9389b on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 4] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogCDGlEC', '-x'] From python-checkins at python.org Fri Feb 7 04:07:30 2014 From: python-checkins at python.org (yury.selivanov) Date: Fri, 7 Feb 2014 04:07:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Etasks=3A_Fix_as?= =?utf-8?q?=5Fcompleted=2C_gather_=26_wait_to_work_with_duplicate_coroutin?= =?utf-8?q?es?= Message-ID: <3fL1dt6YYlzSsF@mail.python.org> http://hg.python.org/cpython/rev/844879389a17 changeset: 89006:844879389a17 user: Yury Selivanov date: Thu Feb 06 22:06:16 2014 -0500 summary: asyncio.tasks: Fix as_completed, gather & wait to work with duplicate coroutines files: Lib/asyncio/tasks.py | 7 +- Lib/test/test_asyncio/test_tasks.py | 55 ++++++++++++++-- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -364,7 +364,7 @@ if loop is None: loop = events.get_event_loop() - fs = set(async(f, loop=loop) for f in fs) + fs = {async(f, loop=loop) for f in set(fs)} if return_when not in (FIRST_COMPLETED, FIRST_EXCEPTION, ALL_COMPLETED): raise ValueError('Invalid return_when value: {}'.format(return_when)) @@ -476,7 +476,7 @@ """ loop = loop if loop is not None else events.get_event_loop() deadline = None if timeout is None else loop.time() + timeout - todo = set(async(f, loop=loop) for f in fs) + todo = {async(f, loop=loop) for f in set(fs)} completed = collections.deque() @coroutine @@ -568,7 +568,8 @@ prevent the cancellation of one child to cause other children to be cancelled.) """ - children = [async(fut, loop=loop) for fut in coros_or_futures] + arg_to_fut = {arg: async(arg, loop=loop) for arg in set(coros_or_futures)} + children = [arg_to_fut[arg] for arg in coros_or_futures] n = len(children) if n == 0: outer = futures.Future(loop=loop) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -483,6 +483,21 @@ self.assertEqual(res, 42) + def test_wait_duplicate_coroutines(self): + @asyncio.coroutine + def coro(s): + return s + c = coro('test') + + task = asyncio.Task( + asyncio.wait([c, c, coro('spam')], loop=self.loop), + loop=self.loop) + + done, pending = self.loop.run_until_complete(task) + + self.assertFalse(pending) + self.assertEqual(set(f.result() for f in done), {'test', 'spam'}) + def test_wait_errors(self): self.assertRaises( ValueError, self.loop.run_until_complete, @@ -757,14 +772,10 @@ def test_as_completed_with_timeout(self): def gen(): - when = yield - self.assertAlmostEqual(0.12, when) - when = yield 0 - self.assertAlmostEqual(0.1, when) - when = yield 0 - self.assertAlmostEqual(0.15, when) - when = yield 0.1 - self.assertAlmostEqual(0.12, when) + yield + yield 0 + yield 0 + yield 0.1 yield 0.02 loop = test_utils.TestLoop(gen) @@ -840,6 +851,25 @@ done, pending = loop.run_until_complete(waiter) self.assertEqual(set(f.result() for f in done), {'a', 'b'}) + def test_as_completed_duplicate_coroutines(self): + @asyncio.coroutine + def coro(s): + return s + + @asyncio.coroutine + def runner(): + result = [] + c = coro('ham') + for f in asyncio.as_completed({c, c, coro('spam')}, loop=self.loop): + result.append((yield from f)) + return result + + fut = asyncio.Task(runner(), loop=self.loop) + self.loop.run_until_complete(fut) + result = fut.result() + self.assertEqual(set(result), {'ham', 'spam'}) + self.assertEqual(len(result), 2) + def test_sleep(self): def gen(): @@ -1505,6 +1535,15 @@ gen3.close() gen4.close() + def test_duplicate_coroutines(self): + @asyncio.coroutine + def coro(s): + return s + c = coro('abc') + fut = asyncio.gather(c, c, coro('def'), c, loop=self.one_loop) + self._run_loop(self.one_loop) + self.assertEqual(fut.result(), ['abc', 'abc', 'def', 'abc']) + def test_cancellation_broadcast(self): # Cancelling outer() cancels all children. proof = 0 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 09:11:06 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 7 Feb 2014 09:11:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTMy?= =?utf-8?q?=3A_Tests_which_use_=5Ftestcapi_now_are_marked_as_CPython_only?= =?utf-8?q?=2E?= Message-ID: <3fL8NB5HJjz7LjP@mail.python.org> http://hg.python.org/cpython/rev/75c75d90f3a4 changeset: 89007:75c75d90f3a4 branch: 2.7 parent: 88988:305b6a5da852 user: Serhiy Storchaka date: Fri Feb 07 10:06:05 2014 +0200 summary: Issue #20532: Tests which use _testcapi now are marked as CPython only. files: Lib/test/string_tests.py | 33 ++++--- Lib/test/test_capi.py | 4 +- Lib/test/test_code.py | 5 +- Lib/test/test_codecs.py | 88 ++++++++++++++-------- Lib/test/test_descr.py | 1 + Lib/test/test_fcntl.py | 46 ++++++---- Lib/test/test_fileio.py | 7 +- Lib/test/test_format.py | 22 ++++- Lib/test/test_getargs2.py | 2 + Lib/test/test_poll.py | 15 +++- Lib/test/test_socket.py | 29 ++++++- Lib/test/test_structmembers.py | 8 +- Lib/test/test_support.py | 2 +- Lib/test/test_sys.py | 1 + Lib/test/test_tcl.py | 13 ++- Lib/test/test_threading.py | 3 +- Lib/test/test_traceback.py | 5 +- Lib/test/test_ucn.py | 20 ++-- Lib/test/test_unicode.py | 9 ++- Misc/NEWS | 2 + 20 files changed, 208 insertions(+), 107 deletions(-) diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -5,7 +5,6 @@ import unittest, string, sys, struct from test import test_support from UserList import UserList -import _testcapi class Sequence: def __init__(self, seq='wxyz'): self.seq = seq @@ -1114,20 +1113,6 @@ self.checkraises(TypeError, '%10.*f', '__mod__', ('foo', 42.)) self.checkraises(ValueError, '%10', '__mod__', (42,)) - width = int(_testcapi.PY_SSIZE_T_MAX + 1) - if width <= sys.maxint: - self.checkraises(OverflowError, '%*s', '__mod__', (width, '')) - prec = int(_testcapi.INT_MAX + 1) - if prec <= sys.maxint: - self.checkraises(OverflowError, '%.*f', '__mod__', (prec, 1. / 7)) - # Issue 15989 - width = int(1 << (_testcapi.PY_SSIZE_T_MAX.bit_length() + 1)) - if width <= sys.maxint: - self.checkraises(OverflowError, '%*s', '__mod__', (width, '')) - prec = int(_testcapi.UINT_MAX + 1) - if prec <= sys.maxint: - self.checkraises(OverflowError, '%.*f', '__mod__', (prec, 1. / 7)) - class X(object): pass self.checkraises(TypeError, 'abc', '__mod__', X()) class X(Exception): @@ -1135,6 +1120,24 @@ return k self.checkequal('melon apple', '%(melon)s %(apple)s', '__mod__', X()) + @test_support.cpython_only + def test_formatting_c_limits(self): + from _testcapi import PY_SSIZE_T_MAX, INT_MAX, UINT_MAX + SIZE_MAX = (1 << (PY_SSIZE_T_MAX.bit_length() + 1)) - 1 + width = int(PY_SSIZE_T_MAX + 1) + if width <= sys.maxint: + self.checkraises(OverflowError, '%*s', '__mod__', (width, '')) + prec = int(INT_MAX + 1) + if prec <= sys.maxint: + self.checkraises(OverflowError, '%.*f', '__mod__', (prec, 1. / 7)) + # Issue 15989 + width = int(SIZE_MAX + 1) + if width <= sys.maxint: + self.checkraises(OverflowError, '%*s', '__mod__', (width, '')) + prec = int(UINT_MAX + 1) + if prec <= sys.maxint: + self.checkraises(OverflowError, '%.*f', '__mod__', (prec, 1. / 7)) + def test_floatformatting(self): # float formatting for prec in xrange(100): diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -13,7 +13,9 @@ except ImportError: thread = None threading = None -import _testcapi +# Skip this test if the _testcapi module isn't available. +_testcapi = test_support.import_module('_testcapi') + @unittest.skipUnless(threading, 'Threading required for this test.') class TestPendingCalls(unittest.TestCase): diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -82,7 +82,7 @@ import unittest import weakref -import _testcapi +from test.test_support import run_doctest, run_unittest, cpython_only def consts(t): @@ -104,7 +104,9 @@ class CodeTest(unittest.TestCase): + @cpython_only def test_newempty(self): + import _testcapi co = _testcapi.code_newempty("filename", "funcname", 15) self.assertEqual(co.co_filename, "filename") self.assertEqual(co.co_name, "funcname") @@ -137,7 +139,6 @@ def test_main(verbose=None): - from test.test_support import run_doctest, run_unittest from test import test_code run_doctest(test_code, verbose) run_unittest(CodeTest, CodeWeakRefTest) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -2,7 +2,7 @@ import unittest import codecs import locale -import sys, StringIO, _testcapi +import sys, StringIO def coding_checker(self, coder): def check(input, expect): @@ -1539,7 +1539,7 @@ class BasicUnicodeTest(unittest.TestCase): def test_basics(self): - s = u"abc123" # all codecs should be able to encode these + s = u"abc123" # all codecs should be able to encode these for encoding in all_unicode_encodings: name = codecs.lookup(encoding).name if encoding.endswith("_codec"): @@ -1548,9 +1548,9 @@ name = "latin_1" self.assertEqual(encoding.replace("_", "-"), name.replace("_", "-")) (bytes, size) = codecs.getencoder(encoding)(s) - self.assertEqual(size, len(s), "%r != %r (encoding=%r)" % (size, len(s), encoding)) + self.assertEqual(size, len(s), "encoding=%r" % encoding) (chars, size) = codecs.getdecoder(encoding)(bytes) - self.assertEqual(chars, s, "%r != %r (encoding=%r)" % (chars, s, encoding)) + self.assertEqual(chars, s, "encoding=%r" % encoding) if encoding not in broken_unicode_with_streams: # check stream reader/writer @@ -1566,15 +1566,13 @@ for c in encodedresult: q.write(c) decodedresult += reader.read() - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + self.assertEqual(decodedresult, s, "encoding=%r" % encoding) if encoding not in broken_incremental_coders: - # check incremental decoder/encoder (fetched via the Python - # and C API) and iterencode()/iterdecode() + # check incremental decoder/encoder and iterencode()/iterdecode() try: encoder = codecs.getincrementalencoder(encoding)() - cencoder = _testcapi.codec_incrementalencoder(encoding) - except LookupError: # no IncrementalEncoder + except LookupError: # no IncrementalEncoder pass else: # check incremental decoder/encoder @@ -1587,45 +1585,71 @@ for c in encodedresult: decodedresult += decoder.decode(c) decodedresult += decoder.decode("", True) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) - - # check C API - encodedresult = "" - for c in s: - encodedresult += cencoder.encode(c) - encodedresult += cencoder.encode(u"", True) - cdecoder = _testcapi.codec_incrementaldecoder(encoding) - decodedresult = u"" - for c in encodedresult: - decodedresult += cdecoder.decode(c) - decodedresult += cdecoder.decode("", True) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) # check iterencode()/iterdecode() - result = u"".join(codecs.iterdecode(codecs.iterencode(s, encoding), encoding)) - self.assertEqual(result, s, "%r != %r (encoding=%r)" % (result, s, encoding)) + result = u"".join(codecs.iterdecode( + codecs.iterencode(s, encoding), encoding)) + self.assertEqual(result, s, "encoding=%r" % encoding) # check iterencode()/iterdecode() with empty string - result = u"".join(codecs.iterdecode(codecs.iterencode(u"", encoding), encoding)) + result = u"".join(codecs.iterdecode( + codecs.iterencode(u"", encoding), encoding)) self.assertEqual(result, u"") if encoding not in only_strict_mode: # check incremental decoder/encoder with errors argument try: encoder = codecs.getincrementalencoder(encoding)("ignore") - cencoder = _testcapi.codec_incrementalencoder(encoding, "ignore") - except LookupError: # no IncrementalEncoder + except LookupError: # no IncrementalEncoder pass else: encodedresult = "".join(encoder.encode(c) for c in s) decoder = codecs.getincrementaldecoder(encoding)("ignore") - decodedresult = u"".join(decoder.decode(c) for c in encodedresult) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + decodedresult = u"".join(decoder.decode(c) + for c in encodedresult) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) + @test_support.cpython_only + def test_basics_capi(self): + from _testcapi import codec_incrementalencoder, codec_incrementaldecoder + s = u"abc123" # all codecs should be able to encode these + for encoding in all_unicode_encodings: + if encoding not in broken_incremental_coders: + # check incremental decoder/encoder and iterencode()/iterdecode() + try: + cencoder = codec_incrementalencoder(encoding) + except LookupError: # no IncrementalEncoder + pass + else: + # check C API + encodedresult = "" + for c in s: + encodedresult += cencoder.encode(c) + encodedresult += cencoder.encode(u"", True) + cdecoder = codec_incrementaldecoder(encoding) + decodedresult = u"" + for c in encodedresult: + decodedresult += cdecoder.decode(c) + decodedresult += cdecoder.decode("", True) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) + + if encoding not in only_strict_mode: + # check incremental decoder/encoder with errors argument + try: + cencoder = codec_incrementalencoder(encoding, "ignore") + except LookupError: # no IncrementalEncoder + pass + else: encodedresult = "".join(cencoder.encode(c) for c in s) - cdecoder = _testcapi.codec_incrementaldecoder(encoding, "ignore") - decodedresult = u"".join(cdecoder.decode(c) for c in encodedresult) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + cdecoder = codec_incrementaldecoder(encoding, "ignore") + decodedresult = u"".join(cdecoder.decode(c) + for c in encodedresult) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) def test_seek(self): # all codecs should be able to encode these diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -2092,6 +2092,7 @@ prop2 = property(fset=setter) self.assertEqual(prop2.__doc__, None) + @test_support.cpython_only def test_testcapi_no_segfault(self): # this segfaulted in 2.5b2 try: diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -6,10 +6,9 @@ import os import struct import sys -import _testcapi import unittest from test.test_support import (verbose, TESTFN, unlink, run_unittest, - import_module) + import_module, cpython_only) # Skip test if no fcntl module. fcntl = import_module('fcntl') @@ -52,6 +51,12 @@ lockdata = get_lockdata() +class BadFile: + def __init__(self, fn): + self.fn = fn + def fileno(self): + return self.fn + class TestFcntl(unittest.TestCase): def setUp(self): @@ -83,24 +88,27 @@ self.f.close() def test_fcntl_bad_file(self): - class F: - def __init__(self, fn): - self.fn = fn - def fileno(self): - return self.fn - self.assertRaises(ValueError, fcntl.fcntl, -1, fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(ValueError, fcntl.fcntl, F(-1), fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(TypeError, fcntl.fcntl, 'spam', fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(TypeError, fcntl.fcntl, F('spam'), fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(ValueError): + fcntl.fcntl(-1, fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(ValueError): + fcntl.fcntl(BadFile(-1), fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(TypeError): + fcntl.fcntl('spam', fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(TypeError): + fcntl.fcntl(BadFile('spam'), fcntl.F_SETFL, os.O_NONBLOCK) + + @cpython_only + def test_fcntl_bad_file_overflow(self): + from _testcapi import INT_MAX, INT_MIN # Issue 15989 - self.assertRaises(ValueError, fcntl.fcntl, _testcapi.INT_MAX + 1, - fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(ValueError, fcntl.fcntl, F(_testcapi.INT_MAX + 1), - fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(ValueError, fcntl.fcntl, _testcapi.INT_MIN - 1, - fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(ValueError, fcntl.fcntl, F(_testcapi.INT_MIN - 1), - fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(ValueError): + fcntl.fcntl(INT_MAX + 1, fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(ValueError): + fcntl.fcntl(BadFile(INT_MAX + 1), fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(ValueError): + fcntl.fcntl(INT_MIN - 1, fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(ValueError): + fcntl.fcntl(BadFile(INT_MIN - 1), fcntl.F_SETFL, os.O_NONBLOCK) def test_fcntl_64_bit(self): # Issue #1309352: fcntl shouldn't fail when the third arg fits in a diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -10,10 +10,9 @@ from weakref import proxy from functools import wraps from UserList import UserList -import _testcapi from test.test_support import TESTFN, check_warnings, run_unittest, make_bad_fd -from test.test_support import py3k_bytes as bytes +from test.test_support import py3k_bytes as bytes, cpython_only from test.script_helper import run_python from _io import FileIO as _FileIO @@ -359,7 +358,11 @@ if sys.platform == 'win32': import msvcrt self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd()) + + @cpython_only + def testInvalidFd_overflow(self): # Issue 15989 + import _testcapi self.assertRaises(TypeError, _FileIO, _testcapi.INT_MAX + 1) self.assertRaises(TypeError, _FileIO, _testcapi.INT_MIN - 1) diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -303,21 +303,31 @@ test_support.run_unittest(FormatTest) def test_precision(self): - INT_MAX = 2147483647 - f = 1.2 self.assertEqual(format(f, ".0f"), "1") self.assertEqual(format(f, ".3f"), "1.200") with self.assertRaises(ValueError) as cm: - format(f, ".%sf" % (INT_MAX + 1)) + format(f, ".%sf" % (sys.maxsize + 1)) self.assertEqual(str(cm.exception), "precision too big") c = complex(f) - self.assertEqual(format(f, ".0f"), "1") - self.assertEqual(format(f, ".3f"), "1.200") + self.assertEqual(format(c, ".0f"), "1+0j") + self.assertEqual(format(c, ".3f"), "1.200+0.000j") + with self.assertRaises(ValueError) as cm: + format(c, ".%sf" % (sys.maxsize + 1)) + self.assertEqual(str(cm.exception), "precision too big") + + @test_support.cpython_only + def test_precision_c_limits(self): + from _testcapi import INT_MAX + + f = 1.2 with self.assertRaises(ValueError) as cm: format(f, ".%sf" % (INT_MAX + 1)) - self.assertEqual(str(cm.exception), "precision too big") + + c = complex(f) + with self.assertRaises(ValueError) as cm: + format(c, ".%sf" % (INT_MAX + 1)) if __name__ == "__main__": diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py --- a/Lib/test/test_getargs2.py +++ b/Lib/test/test_getargs2.py @@ -1,5 +1,7 @@ import unittest from test import test_support +# Skip this test if the _testcapi module isn't available. +test_support.import_module('_testcapi') from _testcapi import getargs_keywords import warnings diff --git a/Lib/test/test_poll.py b/Lib/test/test_poll.py --- a/Lib/test/test_poll.py +++ b/Lib/test/test_poll.py @@ -3,14 +3,13 @@ import os import random import select -from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX try: import threading except ImportError: threading = None import time import unittest -from test.test_support import TESTFN, run_unittest, reap_threads +from test.test_support import TESTFN, run_unittest, reap_threads, cpython_only try: select.poll @@ -161,8 +160,18 @@ # Issues #15989, #17919 self.assertRaises(OverflowError, pollster.register, 0, -1) + self.assertRaises(OverflowError, pollster.register, 0, 1 << 64) + self.assertRaises(OverflowError, pollster.modify, 1, -1) + self.assertRaises(OverflowError, pollster.modify, 1, 1 << 64) + + @cpython_only + def test_poll_c_limits(self): + from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX + pollster = select.poll() + pollster.register(1) + + # Issues #15989, #17919 self.assertRaises(OverflowError, pollster.register, 0, USHRT_MAX + 1) - self.assertRaises(OverflowError, pollster.modify, 1, -1) self.assertRaises(OverflowError, pollster.modify, 1, USHRT_MAX + 1) self.assertRaises(OverflowError, pollster.poll, INT_MAX + 1) self.assertRaises(OverflowError, pollster.poll, UINT_MAX + 1) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -4,7 +4,6 @@ import errno import socket import select -import _testcapi import time import traceback import Queue @@ -711,7 +710,10 @@ srv.listen(backlog) srv.close() + @test_support.cpython_only + def test_listen_backlog_overflow(self): # Issue 15989 + import _testcapi srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.bind((HOST, 0)) self.assertRaises(OverflowError, srv.listen, _testcapi.INT_MAX + 1) @@ -818,6 +820,14 @@ def _testShutdown(self): self.serv_conn.send(MSG) + self.serv_conn.shutdown(2) + + testShutdown_overflow = test_support.cpython_only(testShutdown) + + @test_support.cpython_only + def _testShutdown_overflow(self): + import _testcapi + self.serv_conn.send(MSG) # Issue 15989 self.assertRaises(OverflowError, self.serv_conn.shutdown, _testcapi.INT_MAX + 1) @@ -911,14 +921,23 @@ pass end = time.time() self.assertTrue((end - start) < 1.0, "Error setting non-blocking mode.") - # Issue 15989 - if _testcapi.UINT_MAX < _testcapi.ULONG_MAX: - self.serv.setblocking(_testcapi.UINT_MAX + 1) - self.assertIsNone(self.serv.gettimeout()) def _testSetBlocking(self): pass + @test_support.cpython_only + def testSetBlocking_overflow(self): + # Issue 15989 + import _testcapi + if _testcapi.UINT_MAX >= _testcapi.ULONG_MAX: + self.skipTest('needs UINT_MAX < ULONG_MAX') + self.serv.setblocking(False) + self.assertEqual(self.serv.gettimeout(), 0.0) + self.serv.setblocking(_testcapi.UINT_MAX + 1) + self.assertIsNone(self.serv.gettimeout()) + + _testSetBlocking_overflow = test_support.cpython_only(_testSetBlocking) + def testAccept(self): # Testing non-blocking accept self.serv.setblocking(0) diff --git a/Lib/test/test_structmembers.py b/Lib/test/test_structmembers.py --- a/Lib/test/test_structmembers.py +++ b/Lib/test/test_structmembers.py @@ -1,3 +1,8 @@ +import unittest +from test import test_support + +# Skip this test if the _testcapi module isn't available. +test_support.import_module('_testcapi') from _testcapi import _test_structmembersType, \ CHAR_MAX, CHAR_MIN, UCHAR_MAX, \ SHRT_MAX, SHRT_MIN, USHRT_MAX, \ @@ -5,9 +10,6 @@ LONG_MAX, LONG_MIN, ULONG_MAX, \ LLONG_MAX, LLONG_MIN, ULLONG_MAX -import unittest -from test import test_support - ts=_test_structmembersType(False, 1, 2, 3, 4, 5, 6, 7, 8, 9.99999, 10.1010101010, "hi") diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -19,7 +19,6 @@ import re import time import struct -import _testcapi import sysconfig try: import thread @@ -1002,6 +1001,7 @@ _TPFLAGS_HEAPTYPE = 1<<9 def check_sizeof(test, o, size): + import _testcapi result = sys.getsizeof(o) # add GC header size if ((type(o) == type) and (o.__flags__ & _TPFLAGS_HEAPTYPE) or\ diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -489,6 +489,7 @@ p.wait() self.assertIn(executable, ["''", repr(sys.executable)]) + at test.test_support.cpython_only class SizeofTest(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -1,7 +1,6 @@ import unittest import sys import os -import _testcapi from test import test_support from subprocess import Popen, PIPE @@ -11,6 +10,11 @@ from Tkinter import Tcl from _tkinter import TclError +try: + from _testcapi import INT_MAX, PY_SSIZE_T_MAX +except ImportError: + INT_MAX = PY_SSIZE_T_MAX = sys.maxsize + tcl_version = _tkinter.TCL_VERSION.split('.') try: for i in range(len(tcl_version)): @@ -523,10 +527,9 @@ def setUp(self): self.interp = Tcl() - @unittest.skipUnless(_testcapi.INT_MAX < _testcapi.PY_SSIZE_T_MAX, - "needs UINT_MAX < SIZE_MAX") - @test_support.precisionbigmemtest(size=_testcapi.INT_MAX + 1, memuse=5, - dry_run=False) + @test_support.cpython_only + @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX") + @test_support.precisionbigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False) def test_huge_string(self, size): value = ' ' * size self.assertRaises(OverflowError, self.interp.call, 'set', '_', value) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -1,7 +1,7 @@ # Very rudimentary test of threading module import test.test_support -from test.test_support import verbose +from test.test_support import verbose, cpython_only from test.script_helper import assert_python_ok import random @@ -724,6 +724,7 @@ for t in threads: t.join() + @cpython_only @unittest.skipIf(_testcapi is None, "need _testcapi module") def test_frame_tstate_tracing(self): # Issue #14432: Crash when a generator is created in a C thread that is diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -1,11 +1,10 @@ """Test cases for traceback module""" -from _testcapi import traceback_print from StringIO import StringIO import sys import unittest from imp import reload -from test.test_support import run_unittest, is_jython, Error +from test.test_support import run_unittest, is_jython, Error, cpython_only import traceback @@ -181,7 +180,9 @@ class TracebackFormatTests(unittest.TestCase): + @cpython_only def test_traceback_format(self): + from _testcapi import traceback_print try: raise KeyError('blah') except KeyError: diff --git a/Lib/test/test_ucn.py b/Lib/test/test_ucn.py --- a/Lib/test/test_ucn.py +++ b/Lib/test/test_ucn.py @@ -9,10 +9,14 @@ import unittest import sys -import _testcapi from test import test_support +try: + from _testcapi import INT_MAX, PY_SSIZE_T_MAX, UINT_MAX +except ImportError: + INT_MAX = PY_SSIZE_T_MAX = UINT_MAX = 2**64 - 1 + class UnicodeNamesTest(unittest.TestCase): def checkletter(self, name, code): @@ -139,11 +143,10 @@ unicode, "\\NSPACE", 'unicode-escape', 'strict' ) - @unittest.skipUnless(_testcapi.INT_MAX < _testcapi.PY_SSIZE_T_MAX, - "needs UINT_MAX < SIZE_MAX") - @unittest.skipUnless(_testcapi.UINT_MAX < sys.maxint, - "needs UINT_MAX < sys.maxint") - @test_support.bigmemtest(minsize=_testcapi.UINT_MAX + 1, + @test_support.cpython_only + @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX") + @unittest.skipUnless(UINT_MAX < sys.maxint, "needs UINT_MAX < sys.maxint") + @test_support.bigmemtest(minsize=UINT_MAX + 1, memuse=2 + 4 // len(u'\U00010000')) def test_issue16335(self, size): func = self.test_issue16335 @@ -151,9 +154,8 @@ raise unittest.SkipTest("not enough memory: %.1fG minimum needed" % (func.minsize * func.memuse / float(1024**3),)) # very very long bogus character name - x = b'\\N{SPACE' + b'x' * int(_testcapi.UINT_MAX + 1) + b'}' - self.assertEqual(len(x), len(b'\\N{SPACE}') + - (_testcapi.UINT_MAX + 1)) + x = b'\\N{SPACE' + b'x' * int(UINT_MAX + 1) + b'}' + self.assertEqual(len(x), len(b'\\N{SPACE}') + (UINT_MAX + 1)) self.assertRaisesRegexp(UnicodeError, 'unknown Unicode character name', x.decode, 'unicode-escape' diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -644,8 +644,13 @@ return u'\u1234' self.assertEqual('%s' % Wrapper(), u'\u1234') + def test_formatting_huge_precision(self): + format_string = u"%.{}f".format(sys.maxsize + 1) + with self.assertRaises(ValueError): + result = format_string % 2.34 + @test_support.cpython_only - def test_formatting_huge_precision(self): + def test_formatting_huge_precision_c_limits(self): from _testcapi import INT_MAX format_string = u"%.{}f".format(INT_MAX + 1) with self.assertRaises(ValueError): @@ -1633,6 +1638,7 @@ self.assertEqual("%s" % u, u'__unicode__ overridden') self.assertEqual("{}".format(u), '__unicode__ overridden') + @test_support.cpython_only def test_encode_decimal(self): from _testcapi import unicode_encodedecimal self.assertEqual(unicode_encodedecimal(u'123'), @@ -1658,6 +1664,7 @@ self.assertEqual(unicode_encodedecimal(u"123\u20ac\u0660", "replace"), b'123?0') + @test_support.cpython_only def test_encode_decimal_with_surrogates(self): from _testcapi import unicode_encodedecimal tests = [(u'\U0001f49d', '💝'), diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -224,6 +224,8 @@ Tests ----- +- Issue #20532: Tests which use _testcapi now are marked as CPython only. + - Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. - Issue #19990: Added tests for the imghdr module. Based on patch by -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 09:11:08 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 7 Feb 2014 09:11:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTMy?= =?utf-8?q?=3A_Tests_which_use_=5Ftestcapi_now_are_marked_as_CPython_only?= =?utf-8?q?=2E?= Message-ID: <3fL8ND3Qgsz7Ljt@mail.python.org> http://hg.python.org/cpython/rev/e5a78f7c2dcb changeset: 89008:e5a78f7c2dcb branch: 3.3 parent: 89003:98d9d152e94b user: Serhiy Storchaka date: Fri Feb 07 10:06:39 2014 +0200 summary: Issue #20532: Tests which use _testcapi now are marked as CPython only. files: Lib/test/string_tests.py | 25 ++++-- Lib/test/support/__init__.py | 2 +- Lib/test/test_capi.py | 3 +- Lib/test/test_code.py | 5 +- Lib/test/test_codecs.py | 87 +++++++++++++-------- Lib/test/test_descr.py | 1 + Lib/test/test_devpoll.py | 15 +++- Lib/test/test_exceptions.py | 2 + Lib/test/test_fcntl.py | 47 +++++++---- Lib/test/test_fileio.py | 7 +- Lib/test/test_format.py | 22 ++++- Lib/test/test_getargs2.py | 2 + Lib/test/test_io.py | 5 +- Lib/test/test_poll.py | 15 +++- Lib/test/test_posix.py | 6 +- Lib/test/test_socket.py | 36 +++++++- Lib/test/test_structmembers.py | 8 +- Lib/test/test_sys.py | 1 + Lib/test/test_tcl.py | 12 ++- Lib/test/test_threading.py | 3 +- Lib/test/test_time.py | 3 + Lib/test/test_traceback.py | 7 +- Lib/test/test_ucn.py | 18 ++-- Lib/test/test_unicode.py | 11 ++- Misc/NEWS | 2 + 25 files changed, 239 insertions(+), 106 deletions(-) diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -5,7 +5,6 @@ import unittest, string, sys, struct from test import support from collections import UserList -import _testcapi class Sequence: def __init__(self, seq='wxyz'): self.seq = seq @@ -1185,20 +1184,28 @@ # Outrageously large width or precision should raise ValueError. self.checkraises(ValueError, '%%%df' % (2**64), '__mod__', (3.2)) self.checkraises(ValueError, '%%.%df' % (2**64), '__mod__', (3.2)) - self.checkraises(OverflowError, '%*s', '__mod__', - (_testcapi.PY_SSIZE_T_MAX + 1, '')) + (sys.maxsize + 1, '')) self.checkraises(OverflowError, '%.*f', '__mod__', - (_testcapi.INT_MAX + 1, 1. / 7)) - # Issue 15989 - self.checkraises(OverflowError, '%*s', '__mod__', - (1 << (_testcapi.PY_SSIZE_T_MAX.bit_length() + 1), '')) - self.checkraises(OverflowError, '%.*f', '__mod__', - (_testcapi.UINT_MAX + 1, 1. / 7)) + (sys.maxsize + 1, 1. / 7)) class X(object): pass self.checkraises(TypeError, 'abc', '__mod__', X()) + @support.cpython_only + def test_formatting_c_limits(self): + from _testcapi import PY_SSIZE_T_MAX, INT_MAX, UINT_MAX + SIZE_MAX = (1 << (PY_SSIZE_T_MAX.bit_length() + 1)) - 1 + self.checkraises(OverflowError, '%*s', '__mod__', + (PY_SSIZE_T_MAX + 1, '')) + self.checkraises(OverflowError, '%.*f', '__mod__', + (INT_MAX + 1, 1. / 7)) + # Issue 15989 + self.checkraises(OverflowError, '%*s', '__mod__', + (SIZE_MAX + 1, '')) + self.checkraises(OverflowError, '%.*f', '__mod__', + (UINT_MAX + 1, 1. / 7)) + def test_floatformatting(self): # float formatting for prec in range(100): diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -25,7 +25,6 @@ import logging.handlers import struct import tempfile -import _testcapi try: import _thread, threading @@ -1349,6 +1348,7 @@ _TPFLAGS_HEAPTYPE = 1<<9 def check_sizeof(test, o, size): + import _testcapi result = sys.getsizeof(o) # add GC header size if ((type(o) == type) and (o.__flags__ & _TPFLAGS_HEAPTYPE) or\ diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -17,7 +17,8 @@ import threading except ImportError: threading = None -import _testcapi +# Skip this test if the _testcapi module isn't available. +_testcapi = support.import_module('_testcapi') def testfunction(self): diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -104,7 +104,7 @@ import unittest import weakref -import _testcapi +from test.support import run_doctest, run_unittest, cpython_only def consts(t): @@ -126,7 +126,9 @@ class CodeTest(unittest.TestCase): + @cpython_only def test_newempty(self): + import _testcapi co = _testcapi.code_newempty("filename", "funcname", 15) self.assertEqual(co.co_filename, "filename") self.assertEqual(co.co_name, "funcname") @@ -159,7 +161,6 @@ def test_main(verbose=None): - from test.support import run_doctest, run_unittest from test import test_code run_doctest(test_code, verbose) run_unittest(CodeTest, CodeWeakRefTest) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1,4 +1,3 @@ -import _testcapi import codecs import io import locale @@ -1710,7 +1709,7 @@ class BasicUnicodeTest(unittest.TestCase, MixInCheckStateHandling): def test_basics(self): - s = "abc123" # all codecs should be able to encode these + s = "abc123" # all codecs should be able to encode these for encoding in all_unicode_encodings: name = codecs.lookup(encoding).name if encoding.endswith("_codec"): @@ -1722,9 +1721,9 @@ with support.check_warnings(): # unicode-internal has been deprecated (b, size) = codecs.getencoder(encoding)(s) - self.assertEqual(size, len(s), "%r != %r (encoding=%r)" % (size, len(s), encoding)) + self.assertEqual(size, len(s), "encoding=%r" % encoding) (chars, size) = codecs.getdecoder(encoding)(b) - self.assertEqual(chars, s, "%r != %r (encoding=%r)" % (chars, s, encoding)) + self.assertEqual(chars, s, "encoding=%r" % encoding) if encoding not in broken_unicode_with_streams: # check stream reader/writer @@ -1742,15 +1741,13 @@ for c in encodedresult: q.write(bytes([c])) decodedresult += reader.read() - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + self.assertEqual(decodedresult, s, "encoding=%r" % encoding) if encoding not in broken_incremental_coders: - # check incremental decoder/encoder (fetched via the Python - # and C API) and iterencode()/iterdecode() + # check incremental decoder/encoder and iterencode()/iterdecode() try: encoder = codecs.getincrementalencoder(encoding)() - cencoder = _testcapi.codec_incrementalencoder(encoding) - except LookupError: # no IncrementalEncoder + except LookupError: # no IncrementalEncoder pass else: # check incremental decoder/encoder @@ -1763,45 +1760,71 @@ for c in encodedresult: decodedresult += decoder.decode(bytes([c])) decodedresult += decoder.decode(b"", True) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) - - # check C API - encodedresult = b"" - for c in s: - encodedresult += cencoder.encode(c) - encodedresult += cencoder.encode("", True) - cdecoder = _testcapi.codec_incrementaldecoder(encoding) - decodedresult = "" - for c in encodedresult: - decodedresult += cdecoder.decode(bytes([c])) - decodedresult += cdecoder.decode(b"", True) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) # check iterencode()/iterdecode() - result = "".join(codecs.iterdecode(codecs.iterencode(s, encoding), encoding)) - self.assertEqual(result, s, "%r != %r (encoding=%r)" % (result, s, encoding)) + result = "".join(codecs.iterdecode( + codecs.iterencode(s, encoding), encoding)) + self.assertEqual(result, s, "encoding=%r" % encoding) # check iterencode()/iterdecode() with empty string - result = "".join(codecs.iterdecode(codecs.iterencode("", encoding), encoding)) + result = "".join(codecs.iterdecode( + codecs.iterencode("", encoding), encoding)) self.assertEqual(result, "") if encoding not in ("idna", "mbcs"): # check incremental decoder/encoder with errors argument try: encoder = codecs.getincrementalencoder(encoding)("ignore") - cencoder = _testcapi.codec_incrementalencoder(encoding, "ignore") - except LookupError: # no IncrementalEncoder + except LookupError: # no IncrementalEncoder pass else: encodedresult = b"".join(encoder.encode(c) for c in s) decoder = codecs.getincrementaldecoder(encoding)("ignore") - decodedresult = "".join(decoder.decode(bytes([c])) for c in encodedresult) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + decodedresult = "".join(decoder.decode(bytes([c])) + for c in encodedresult) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) + @support.cpython_only + def test_basics_capi(self): + from _testcapi import codec_incrementalencoder, codec_incrementaldecoder + s = "abc123" # all codecs should be able to encode these + for encoding in all_unicode_encodings: + if encoding not in broken_incremental_coders: + # check incremental decoder/encoder (fetched via the C API) + try: + cencoder = codec_incrementalencoder(encoding) + except LookupError: # no IncrementalEncoder + pass + else: + # check C API + encodedresult = b"" + for c in s: + encodedresult += cencoder.encode(c) + encodedresult += cencoder.encode("", True) + cdecoder = codec_incrementaldecoder(encoding) + decodedresult = "" + for c in encodedresult: + decodedresult += cdecoder.decode(bytes([c])) + decodedresult += cdecoder.decode(b"", True) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) + + if encoding not in ("idna", "mbcs"): + # check incremental decoder/encoder with errors argument + try: + cencoder = codec_incrementalencoder(encoding, "ignore") + except LookupError: # no IncrementalEncoder + pass + else: encodedresult = b"".join(cencoder.encode(c) for c in s) - cdecoder = _testcapi.codec_incrementaldecoder(encoding, "ignore") - decodedresult = "".join(cdecoder.decode(bytes([c])) for c in encodedresult) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + cdecoder = codec_incrementaldecoder(encoding, "ignore") + decodedresult = "".join(cdecoder.decode(bytes([c])) + for c in encodedresult) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) def test_seek(self): # all codecs should be able to encode these diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -2046,6 +2046,7 @@ prop2 = property(fset=setter) self.assertEqual(prop2.__doc__, None) + @support.cpython_only def test_testcapi_no_segfault(self): # this segfaulted in 2.5b2 try: diff --git a/Lib/test/test_devpoll.py b/Lib/test/test_devpoll.py --- a/Lib/test/test_devpoll.py +++ b/Lib/test/test_devpoll.py @@ -3,8 +3,7 @@ # Initial tests are copied as is from "test_poll.py" import os, select, random, unittest, sys -from test.support import TESTFN, run_unittest -from _testcapi import USHRT_MAX +from test.support import TESTFN, run_unittest, cpython_only try: select.devpoll @@ -94,8 +93,18 @@ pollster.register(w) # Issue #17919 self.assertRaises(OverflowError, pollster.register, 0, -1) + self.assertRaises(OverflowError, pollster.register, 0, 1 << 64) + self.assertRaises(OverflowError, pollster.modify, 1, -1) + self.assertRaises(OverflowError, pollster.modify, 1, 1 << 64) + + @cpython_only + def test_events_mask_overflow_c_limits(self): + from _testcapi import USHRT_MAX + pollster = select.devpoll() + w, r = os.pipe() + pollster.register(w) + # Issue #17919 self.assertRaises(OverflowError, pollster.register, 0, USHRT_MAX + 1) - self.assertRaises(OverflowError, pollster.modify, 1, -1) self.assertRaises(OverflowError, pollster.modify, 1, USHRT_MAX + 1) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -832,6 +832,7 @@ self.assertIn("maximum recursion depth exceeded", str(v)) + @cpython_only def test_MemoryError(self): # PyErr_NoMemory always raises the same exception instance. # Check that the traceback is not doubled. @@ -890,6 +891,7 @@ self.assertEqual(error5.a, 1) self.assertEqual(error5.__doc__, "") + @cpython_only def test_memory_error_cleanup(self): # Issue #5437: preallocated MemoryError instances should not keep # traceback objects alive. diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -7,9 +7,9 @@ import os import struct import sys -import _testcapi import unittest -from test.support import verbose, TESTFN, unlink, run_unittest, import_module +from test.support import (verbose, TESTFN, unlink, run_unittest, import_module, + cpython_only) # Skip test if no fcntl module. fcntl = import_module('fcntl') @@ -50,6 +50,12 @@ lockdata = get_lockdata() +class BadFile: + def __init__(self, fn): + self.fn = fn + def fileno(self): + return self.fn + class TestFcntl(unittest.TestCase): def setUp(self): @@ -81,24 +87,27 @@ self.f.close() def test_fcntl_bad_file(self): - class F: - def __init__(self, fn): - self.fn = fn - def fileno(self): - return self.fn - self.assertRaises(ValueError, fcntl.fcntl, -1, fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(ValueError, fcntl.fcntl, F(-1), fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(TypeError, fcntl.fcntl, 'spam', fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(TypeError, fcntl.fcntl, F('spam'), fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(ValueError): + fcntl.fcntl(-1, fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(ValueError): + fcntl.fcntl(BadFile(-1), fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(TypeError): + fcntl.fcntl('spam', fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(TypeError): + fcntl.fcntl(BadFile('spam'), fcntl.F_SETFL, os.O_NONBLOCK) + + @cpython_only + def test_fcntl_bad_file_overflow(self): + from _testcapi import INT_MAX, INT_MIN # Issue 15989 - self.assertRaises(OverflowError, fcntl.fcntl, _testcapi.INT_MAX + 1, - fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(OverflowError, fcntl.fcntl, F(_testcapi.INT_MAX + 1), - fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(OverflowError, fcntl.fcntl, _testcapi.INT_MIN - 1, - fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(OverflowError, fcntl.fcntl, F(_testcapi.INT_MIN - 1), - fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(OverflowError): + fcntl.fcntl(INT_MAX + 1, fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(OverflowError): + fcntl.fcntl(BadFile(INT_MAX + 1), fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(OverflowError): + fcntl.fcntl(INT_MIN - 1, fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(OverflowError): + fcntl.fcntl(BadFile(INT_MIN - 1), fcntl.F_SETFL, os.O_NONBLOCK) @unittest.skipIf( platform.machine().startswith('arm') and platform.system() == 'Linux', diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -8,9 +8,8 @@ from array import array from weakref import proxy from functools import wraps -import _testcapi -from test.support import TESTFN, check_warnings, run_unittest, make_bad_fd +from test.support import TESTFN, check_warnings, run_unittest, make_bad_fd, cpython_only from collections import UserList from _io import FileIO as _FileIO @@ -362,7 +361,11 @@ if sys.platform == 'win32': import msvcrt self.assertRaises(IOError, msvcrt.get_osfhandle, make_bad_fd()) + + @cpython_only + def testInvalidFd_overflow(self): # Issue 15989 + import _testcapi self.assertRaises(TypeError, _FileIO, _testcapi.INT_MAX + 1) self.assertRaises(TypeError, _FileIO, _testcapi.INT_MIN - 1) diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -313,21 +313,31 @@ support.run_unittest(FormatTest) def test_precision(self): - INT_MAX = 2147483647 - f = 1.2 self.assertEqual(format(f, ".0f"), "1") self.assertEqual(format(f, ".3f"), "1.200") with self.assertRaises(ValueError) as cm: - format(f, ".%sf" % (INT_MAX + 1)) + format(f, ".%sf" % (sys.maxsize + 1)) self.assertEqual(str(cm.exception), "precision too big") c = complex(f) - self.assertEqual(format(f, ".0f"), "1") - self.assertEqual(format(f, ".3f"), "1.200") + self.assertEqual(format(c, ".0f"), "1+0j") + self.assertEqual(format(c, ".3f"), "1.200+0.000j") + with self.assertRaises(ValueError) as cm: + format(c, ".%sf" % (sys.maxsize + 1)) + self.assertEqual(str(cm.exception), "precision too big") + + @support.cpython_only + def test_precision_c_limits(self): + from _testcapi import INT_MAX + + f = 1.2 with self.assertRaises(ValueError) as cm: format(f, ".%sf" % (INT_MAX + 1)) - self.assertEqual(str(cm.exception), "precision too big") + + c = complex(f) + with self.assertRaises(ValueError) as cm: + format(c, ".%sf" % (INT_MAX + 1)) if __name__ == "__main__": diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py --- a/Lib/test/test_getargs2.py +++ b/Lib/test/test_getargs2.py @@ -1,5 +1,7 @@ import unittest from test import support +# Skip this test if the _testcapi module isn't available. +support.import_module('_testcapi') from _testcapi import getargs_keywords, getargs_keyword_only """ diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -32,7 +32,6 @@ import unittest import warnings import weakref -import _testcapi from collections import deque, UserList from itertools import cycle, count from test import support @@ -1977,8 +1976,10 @@ os.environ.clear() os.environ.update(old_environ) - # Issue 15989 + @support.cpython_only def test_device_encoding(self): + # Issue 15989 + import _testcapi b = self.BytesIO() b.fileno = lambda: _testcapi.INT_MAX + 1 self.assertRaises(OverflowError, self.TextIOWrapper, b) diff --git a/Lib/test/test_poll.py b/Lib/test/test_poll.py --- a/Lib/test/test_poll.py +++ b/Lib/test/test_poll.py @@ -3,14 +3,13 @@ import os import random import select -from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX try: import threading except ImportError: threading = None import time import unittest -from test.support import TESTFN, run_unittest, reap_threads +from test.support import TESTFN, run_unittest, reap_threads, cpython_only try: select.poll @@ -161,8 +160,18 @@ # Issues #15989, #17919 self.assertRaises(OverflowError, pollster.register, 0, -1) + self.assertRaises(OverflowError, pollster.register, 0, 1 << 64) + self.assertRaises(OverflowError, pollster.modify, 1, -1) + self.assertRaises(OverflowError, pollster.modify, 1, 1 << 64) + + @cpython_only + def test_poll_c_limits(self): + from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX + pollster = select.poll() + pollster.register(1) + + # Issues #15989, #17919 self.assertRaises(OverflowError, pollster.register, 0, USHRT_MAX + 1) - self.assertRaises(OverflowError, pollster.modify, 1, -1) self.assertRaises(OverflowError, pollster.modify, 1, USHRT_MAX + 1) self.assertRaises(OverflowError, pollster.poll, INT_MAX + 1) self.assertRaises(OverflowError, pollster.poll, UINT_MAX + 1) diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -17,7 +17,6 @@ import tempfile import unittest import warnings -import _testcapi _DUMMY_SYMLINK = os.path.join(tempfile.gettempdir(), support.TESTFN + '-dummy-symlink') @@ -615,7 +614,12 @@ except OSError: pass + @support.cpython_only + @unittest.skipUnless(hasattr(os, 'pipe2'), "test needs os.pipe2()") + @support.requires_linux_version(2, 6, 27) + def test_pipe2_c_limits(self): # Issue 15989 + import _testcapi self.assertRaises(OverflowError, os.pipe2, _testcapi.INT_MAX + 1) self.assertRaises(OverflowError, os.pipe2, _testcapi.UINT_MAX + 1) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -7,7 +7,6 @@ import socket import select import tempfile -import _testcapi import time import traceback import queue @@ -1274,7 +1273,10 @@ srv.listen(backlog) srv.close() + @support.cpython_only + def test_listen_backlog_overflow(self): # Issue 15989 + import _testcapi srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.bind((HOST, 0)) self.assertRaises(OverflowError, srv.listen, _testcapi.INT_MAX + 1) @@ -1593,6 +1595,14 @@ def _testShutdown(self): self.serv_conn.send(MSG) + self.serv_conn.shutdown(2) + + testShutdown_overflow = support.cpython_only(testShutdown) + + @support.cpython_only + def _testShutdown_overflow(self): + import _testcapi + self.serv_conn.send(MSG) # Issue 15989 self.assertRaises(OverflowError, self.serv_conn.shutdown, _testcapi.INT_MAX + 1) @@ -2361,7 +2371,12 @@ # code with these functions. # Match the definition in socketmodule.c - socklen_t_limit = min(0x7fffffff, _testcapi.INT_MAX) + try: + import _testcapi + except ImportError: + socklen_t_limit = 0x7fffffff + else: + socklen_t_limit = min(0x7fffffff, _testcapi.INT_MAX) @requireAttrs(socket, "CMSG_LEN") def testCMSG_LEN(self): @@ -3586,14 +3601,23 @@ pass end = time.time() self.assertTrue((end - start) < 1.0, "Error setting non-blocking mode.") - # Issue 15989 - if _testcapi.UINT_MAX < _testcapi.ULONG_MAX: - self.serv.setblocking(_testcapi.UINT_MAX + 1) - self.assertIsNone(self.serv.gettimeout()) def _testSetBlocking(self): pass + @support.cpython_only + def testSetBlocking_overflow(self): + # Issue 15989 + import _testcapi + if _testcapi.UINT_MAX >= _testcapi.ULONG_MAX: + self.skipTest('needs UINT_MAX < ULONG_MAX') + self.serv.setblocking(False) + self.assertEqual(self.serv.gettimeout(), 0.0) + self.serv.setblocking(_testcapi.UINT_MAX + 1) + self.assertIsNone(self.serv.gettimeout()) + + _testSetBlocking_overflow = support.cpython_only(_testSetBlocking) + @unittest.skipUnless(hasattr(socket, 'SOCK_NONBLOCK'), 'test needs socket.SOCK_NONBLOCK') @support.requires_linux_version(2, 6, 28) diff --git a/Lib/test/test_structmembers.py b/Lib/test/test_structmembers.py --- a/Lib/test/test_structmembers.py +++ b/Lib/test/test_structmembers.py @@ -1,3 +1,8 @@ +import unittest +from test import support + +# Skip this test if the _testcapi module isn't available. +support.import_module('_testcapi') from _testcapi import _test_structmembersType, \ CHAR_MAX, CHAR_MIN, UCHAR_MAX, \ SHRT_MAX, SHRT_MIN, USHRT_MAX, \ @@ -6,9 +11,6 @@ LLONG_MAX, LLONG_MIN, ULLONG_MAX, \ PY_SSIZE_T_MAX, PY_SSIZE_T_MIN -import unittest -from test import support - ts=_test_structmembersType(False, # T_BOOL 1, # T_BYTE 2, # T_UBYTE diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -610,6 +610,7 @@ ret, out, err = assert_python_ok(*args) self.assertIn(b"free PyDictObjects", err) + at test.support.cpython_only class SizeofTest(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -1,7 +1,6 @@ import unittest import sys import os -import _testcapi from test import support # Skip this test if the _tkinter module wasn't built. @@ -13,6 +12,11 @@ from tkinter import Tcl from _tkinter import TclError +try: + from _testcapi import INT_MAX, PY_SSIZE_T_MAX +except ImportError: + INT_MAX = PY_SSIZE_T_MAX = sys.maxsize + tcl_version = _tkinter.TCL_VERSION.split('.') try: for i in range(len(tcl_version)): @@ -539,9 +543,9 @@ def setUp(self): self.interp = Tcl() - @unittest.skipUnless(_testcapi.INT_MAX < _testcapi.PY_SSIZE_T_MAX, - "needs UINT_MAX < SIZE_MAX") - @support.bigmemtest(size=_testcapi.INT_MAX + 1, memuse=5, dry_run=False) + @support.cpython_only + @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX") + @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False) def test_huge_string(self, size): value = ' ' * size self.assertRaises(OverflowError, self.interp.call, 'set', '_', value) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -3,7 +3,7 @@ """ import test.support -from test.support import verbose, strip_python_stderr, import_module +from test.support import verbose, strip_python_stderr, import_module, cpython_only from test.script_helper import assert_python_ok import random @@ -773,6 +773,7 @@ for t in threads: t.join() + @cpython_only @unittest.skipIf(_testcapi is None, "need _testcapi module") def test_frame_tstate_tracing(self): # Issue #14432: Crash when a generator is created in a C thread that is diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -573,6 +573,7 @@ -(2.0 ** 100.0), 2.0 ** 100.0, ) + @support.cpython_only def test_time_t(self): from _testcapi import pytime_object_to_time_t for obj, time_t in ( @@ -588,6 +589,7 @@ for invalid in self.invalid_values: self.assertRaises(OverflowError, pytime_object_to_time_t, invalid) + @support.cpython_only def test_timeval(self): from _testcapi import pytime_object_to_timeval for obj, timeval in ( @@ -607,6 +609,7 @@ for invalid in self.invalid_values: self.assertRaises(OverflowError, pytime_object_to_timeval, invalid) + @support.cpython_only def test_timespec(self): from _testcapi import pytime_object_to_timespec for obj, timespec in ( diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -1,12 +1,11 @@ """Test cases for traceback module""" -from _testcapi import traceback_print, exception_print from io import StringIO import sys import unittest import re from test.support import run_unittest, Error, captured_output -from test.support import TESTFN, unlink +from test.support import TESTFN, unlink, cpython_only import traceback @@ -173,7 +172,9 @@ class TracebackFormatTests(unittest.TestCase): + @cpython_only def test_traceback_format(self): + from _testcapi import traceback_print try: raise KeyError('blah') except KeyError: @@ -360,7 +361,9 @@ # This checks built-in reporting by the interpreter. # + @cpython_only def get_report(self, e): + from _testcapi import exception_print e = self.get_exception(e) with captured_output("stderr") as s: exception_print(e) diff --git a/Lib/test/test_ucn.py b/Lib/test/test_ucn.py --- a/Lib/test/test_ucn.py +++ b/Lib/test/test_ucn.py @@ -9,12 +9,16 @@ import unittest import unicodedata -import _testcapi from test import support from http.client import HTTPException from test.test_normalization import check_version +try: + from _testcapi import INT_MAX, PY_SSIZE_T_MAX, UINT_MAX +except ImportError: + INT_MAX = PY_SSIZE_T_MAX = UINT_MAX = 2**64 - 1 + class UnicodeNamesTest(unittest.TestCase): def checkletter(self, name, code): @@ -216,15 +220,13 @@ str, b"\\NSPACE", 'unicode-escape', 'strict' ) - @unittest.skipUnless(_testcapi.INT_MAX < _testcapi.PY_SSIZE_T_MAX, - "needs UINT_MAX < SIZE_MAX") - @support.bigmemtest(size=_testcapi.UINT_MAX + 1, - memuse=2 + 1, dry_run=False) + @support.cpython_only + @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX") + @support.bigmemtest(size=UINT_MAX + 1, memuse=2 + 1, dry_run=False) def test_issue16335(self, size): # very very long bogus character name - x = b'\\N{SPACE' + b'x' * (_testcapi.UINT_MAX + 1) + b'}' - self.assertEqual(len(x), len(b'\\N{SPACE}') + - (_testcapi.UINT_MAX + 1)) + x = b'\\N{SPACE' + b'x' * (UINT_MAX + 1) + b'}' + self.assertEqual(len(x), len(b'\\N{SPACE}') + (UINT_MAX + 1)) self.assertRaisesRegex(UnicodeError, 'unknown Unicode character name', x.decode, 'unicode-escape' diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -1108,8 +1108,13 @@ self.assertEqual('%.1s' % "a\xe9\u20ac", 'a') self.assertEqual('%.2s' % "a\xe9\u20ac", 'a\xe9') + def test_formatting_huge_precision(self): + format_string = "%.{}f".format(sys.maxsize + 1) + with self.assertRaises(ValueError): + result = format_string % 2.34 + @support.cpython_only - def test_formatting_huge_precision(self): + def test_formatting_huge_precision_c_limits(self): from _testcapi import INT_MAX format_string = "%.{}f".format(INT_MAX + 1) with self.assertRaises(ValueError): @@ -2090,6 +2095,7 @@ self.assertEqual(PyUnicode_FromFormat(b'%.%s', b'abc'), '%.%s') # Test PyUnicode_AsWideChar() + @support.cpython_only def test_aswidechar(self): from _testcapi import unicode_aswidechar support.import_module('ctypes') @@ -2127,6 +2133,7 @@ self.assertEqual(wchar, nonbmp + '\0') # Test PyUnicode_AsWideCharString() + @support.cpython_only def test_aswidecharstring(self): from _testcapi import unicode_aswidecharstring support.import_module('ctypes') @@ -2161,6 +2168,7 @@ s += "4" self.assertEqual(s, "3") + @support.cpython_only def test_encode_decimal(self): from _testcapi import unicode_encodedecimal self.assertEqual(unicode_encodedecimal('123'), @@ -2176,6 +2184,7 @@ "^'decimal' codec can't encode character", unicode_encodedecimal, "123\u20ac", "replace") + @support.cpython_only def test_transform_decimal(self): from _testcapi import unicode_transformdecimaltoascii as transform_decimal self.assertEqual(transform_decimal('123'), diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -324,6 +324,8 @@ Tests ----- +- Issue #20532: Tests which use _testcapi are now marked as CPython only. + - Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. - Issue #19990: Added tests for the imghdr module. Based on patch by -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 09:11:10 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 7 Feb 2014 09:11:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320532=3A_Tests_which_use_=5Ftestcapi_now_are_ma?= =?utf-8?q?rked_as_CPython_only=2E?= Message-ID: <3fL8NG1lYpz7Lk2@mail.python.org> http://hg.python.org/cpython/rev/b4e99bec0c8a changeset: 89009:b4e99bec0c8a parent: 89006:844879389a17 parent: 89008:e5a78f7c2dcb user: Serhiy Storchaka date: Fri Feb 07 10:10:55 2014 +0200 summary: Issue #20532: Tests which use _testcapi now are marked as CPython only. files: Lib/test/string_tests.py | 25 ++++-- Lib/test/support/__init__.py | 3 +- Lib/test/test_atexit.py | 1 - Lib/test/test_capi.py | 3 +- Lib/test/test_code.py | 5 +- Lib/test/test_codecs.py | 87 +++++++++++++-------- Lib/test/test_descr.py | 1 + Lib/test/test_devpoll.py | 16 +++- Lib/test/test_exceptions.py | 2 + Lib/test/test_fcntl.py | 51 ++++++++---- Lib/test/test_fileio.py | 7 +- Lib/test/test_finalization.py | 17 +++- Lib/test/test_format.py | 17 +++- Lib/test/test_gc.py | 22 ++++- Lib/test/test_getargs2.py | 2 + Lib/test/test_inspect.py | 13 ++- Lib/test/test_io.py | 5 +- Lib/test/test_poll.py | 15 +++- Lib/test/test_posix.py | 6 +- Lib/test/test_socket.py | 36 +++++++- Lib/test/test_structmembers.py | 8 +- Lib/test/test_sys.py | 1 + Lib/test/test_tcl.py | 12 ++- Lib/test/test_threading.py | 6 +- Lib/test/test_time.py | 3 + Lib/test/test_traceback.py | 7 +- Lib/test/test_ucn.py | 18 ++-- Lib/test/test_unicode.py | 11 ++- Misc/NEWS | 2 + 29 files changed, 284 insertions(+), 118 deletions(-) diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -5,7 +5,6 @@ import unittest, string, sys, struct from test import support from collections import UserList -import _testcapi class Sequence: def __init__(self, seq='wxyz'): self.seq = seq @@ -1199,20 +1198,28 @@ # Outrageously large width or precision should raise ValueError. self.checkraises(ValueError, '%%%df' % (2**64), '__mod__', (3.2)) self.checkraises(ValueError, '%%.%df' % (2**64), '__mod__', (3.2)) - self.checkraises(OverflowError, '%*s', '__mod__', - (_testcapi.PY_SSIZE_T_MAX + 1, '')) + (sys.maxsize + 1, '')) self.checkraises(OverflowError, '%.*f', '__mod__', - (_testcapi.INT_MAX + 1, 1. / 7)) - # Issue 15989 - self.checkraises(OverflowError, '%*s', '__mod__', - (1 << (_testcapi.PY_SSIZE_T_MAX.bit_length() + 1), '')) - self.checkraises(OverflowError, '%.*f', '__mod__', - (_testcapi.UINT_MAX + 1, 1. / 7)) + (sys.maxsize + 1, 1. / 7)) class X(object): pass self.checkraises(TypeError, 'abc', '__mod__', X()) + @support.cpython_only + def test_formatting_c_limits(self): + from _testcapi import PY_SSIZE_T_MAX, INT_MAX, UINT_MAX + SIZE_MAX = (1 << (PY_SSIZE_T_MAX.bit_length() + 1)) - 1 + self.checkraises(OverflowError, '%*s', '__mod__', + (PY_SSIZE_T_MAX + 1, '')) + self.checkraises(OverflowError, '%.*f', '__mod__', + (INT_MAX + 1, 1. / 7)) + # Issue 15989 + self.checkraises(OverflowError, '%*s', '__mod__', + (SIZE_MAX + 1, '')) + self.checkraises(OverflowError, '%.*f', '__mod__', + (UINT_MAX + 1, 1. / 7)) + def test_floatformatting(self): # float formatting for prec in range(100): diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -25,7 +25,6 @@ import logging.handlers import struct import tempfile -import _testcapi try: import _thread, threading @@ -1373,6 +1372,7 @@ _TPFLAGS_HEAPTYPE = 1<<9 def check_sizeof(test, o, size): + import _testcapi result = sys.getsizeof(o) # add GC header size if ((type(o) == type) and (o.__flags__ & _TPFLAGS_HEAPTYPE) or\ @@ -2172,4 +2172,5 @@ raise unittest.SkipTest("run_in_subinterp() cannot be used " "if tracemalloc module is tracing " "memory allocations") + import _testcapi return _testcapi.run_in_subinterp(code) diff --git a/Lib/test/test_atexit.py b/Lib/test/test_atexit.py --- a/Lib/test/test_atexit.py +++ b/Lib/test/test_atexit.py @@ -2,7 +2,6 @@ import unittest import io import atexit -import _testcapi from test import support ### helpers diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -18,7 +18,8 @@ import threading except ImportError: threading = None -import _testcapi +# Skip this test if the _testcapi module isn't available. +_testcapi = support.import_module('_testcapi') def testfunction(self): diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py --- a/Lib/test/test_code.py +++ b/Lib/test/test_code.py @@ -104,7 +104,7 @@ import unittest import weakref -import _testcapi +from test.support import run_doctest, run_unittest, cpython_only def consts(t): @@ -126,7 +126,9 @@ class CodeTest(unittest.TestCase): + @cpython_only def test_newempty(self): + import _testcapi co = _testcapi.code_newempty("filename", "funcname", 15) self.assertEqual(co.co_filename, "filename") self.assertEqual(co.co_name, "funcname") @@ -159,7 +161,6 @@ def test_main(verbose=None): - from test.support import run_doctest, run_unittest from test import test_code run_doctest(test_code, verbose) run_unittest(CodeTest, CodeWeakRefTest) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1,4 +1,3 @@ -import _testcapi import codecs import contextlib import io @@ -1760,7 +1759,7 @@ class BasicUnicodeTest(unittest.TestCase, MixInCheckStateHandling): def test_basics(self): - s = "abc123" # all codecs should be able to encode these + s = "abc123" # all codecs should be able to encode these for encoding in all_unicode_encodings: name = codecs.lookup(encoding).name if encoding.endswith("_codec"): @@ -1772,9 +1771,9 @@ with support.check_warnings(): # unicode-internal has been deprecated (b, size) = codecs.getencoder(encoding)(s) - self.assertEqual(size, len(s), "%r != %r (encoding=%r)" % (size, len(s), encoding)) + self.assertEqual(size, len(s), "encoding=%r" % encoding) (chars, size) = codecs.getdecoder(encoding)(b) - self.assertEqual(chars, s, "%r != %r (encoding=%r)" % (chars, s, encoding)) + self.assertEqual(chars, s, "encoding=%r" % encoding) if encoding not in broken_unicode_with_streams: # check stream reader/writer @@ -1792,15 +1791,13 @@ for c in encodedresult: q.write(bytes([c])) decodedresult += reader.read() - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + self.assertEqual(decodedresult, s, "encoding=%r" % encoding) if encoding not in broken_incremental_coders: - # check incremental decoder/encoder (fetched via the Python - # and C API) and iterencode()/iterdecode() + # check incremental decoder/encoder and iterencode()/iterdecode() try: encoder = codecs.getincrementalencoder(encoding)() - cencoder = _testcapi.codec_incrementalencoder(encoding) - except LookupError: # no IncrementalEncoder + except LookupError: # no IncrementalEncoder pass else: # check incremental decoder/encoder @@ -1813,45 +1810,71 @@ for c in encodedresult: decodedresult += decoder.decode(bytes([c])) decodedresult += decoder.decode(b"", True) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) - - # check C API - encodedresult = b"" - for c in s: - encodedresult += cencoder.encode(c) - encodedresult += cencoder.encode("", True) - cdecoder = _testcapi.codec_incrementaldecoder(encoding) - decodedresult = "" - for c in encodedresult: - decodedresult += cdecoder.decode(bytes([c])) - decodedresult += cdecoder.decode(b"", True) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) # check iterencode()/iterdecode() - result = "".join(codecs.iterdecode(codecs.iterencode(s, encoding), encoding)) - self.assertEqual(result, s, "%r != %r (encoding=%r)" % (result, s, encoding)) + result = "".join(codecs.iterdecode( + codecs.iterencode(s, encoding), encoding)) + self.assertEqual(result, s, "encoding=%r" % encoding) # check iterencode()/iterdecode() with empty string - result = "".join(codecs.iterdecode(codecs.iterencode("", encoding), encoding)) + result = "".join(codecs.iterdecode( + codecs.iterencode("", encoding), encoding)) self.assertEqual(result, "") if encoding not in ("idna", "mbcs"): # check incremental decoder/encoder with errors argument try: encoder = codecs.getincrementalencoder(encoding)("ignore") - cencoder = _testcapi.codec_incrementalencoder(encoding, "ignore") - except LookupError: # no IncrementalEncoder + except LookupError: # no IncrementalEncoder pass else: encodedresult = b"".join(encoder.encode(c) for c in s) decoder = codecs.getincrementaldecoder(encoding)("ignore") - decodedresult = "".join(decoder.decode(bytes([c])) for c in encodedresult) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + decodedresult = "".join(decoder.decode(bytes([c])) + for c in encodedresult) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) + @support.cpython_only + def test_basics_capi(self): + from _testcapi import codec_incrementalencoder, codec_incrementaldecoder + s = "abc123" # all codecs should be able to encode these + for encoding in all_unicode_encodings: + if encoding not in broken_incremental_coders: + # check incremental decoder/encoder (fetched via the C API) + try: + cencoder = codec_incrementalencoder(encoding) + except LookupError: # no IncrementalEncoder + pass + else: + # check C API + encodedresult = b"" + for c in s: + encodedresult += cencoder.encode(c) + encodedresult += cencoder.encode("", True) + cdecoder = codec_incrementaldecoder(encoding) + decodedresult = "" + for c in encodedresult: + decodedresult += cdecoder.decode(bytes([c])) + decodedresult += cdecoder.decode(b"", True) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) + + if encoding not in ("idna", "mbcs"): + # check incremental decoder/encoder with errors argument + try: + cencoder = codec_incrementalencoder(encoding, "ignore") + except LookupError: # no IncrementalEncoder + pass + else: encodedresult = b"".join(cencoder.encode(c) for c in s) - cdecoder = _testcapi.codec_incrementaldecoder(encoding, "ignore") - decodedresult = "".join(cdecoder.decode(bytes([c])) for c in encodedresult) - self.assertEqual(decodedresult, s, "%r != %r (encoding=%r)" % (decodedresult, s, encoding)) + cdecoder = codec_incrementaldecoder(encoding, "ignore") + decodedresult = "".join(cdecoder.decode(bytes([c])) + for c in encodedresult) + self.assertEqual(decodedresult, s, + "encoding=%r" % encoding) def test_seek(self): # all codecs should be able to encode these diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -2050,6 +2050,7 @@ prop2 = property(fset=setter) self.assertEqual(prop2.__doc__, None) + @support.cpython_only def test_testcapi_no_segfault(self): # this segfaulted in 2.5b2 try: diff --git a/Lib/test/test_devpoll.py b/Lib/test/test_devpoll.py --- a/Lib/test/test_devpoll.py +++ b/Lib/test/test_devpoll.py @@ -7,8 +7,7 @@ import select import sys import unittest -from test.support import TESTFN, run_unittest -from _testcapi import USHRT_MAX +from test.support import TESTFN, run_unittest, cpython_only try: select.devpoll @@ -121,15 +120,24 @@ self.addCleanup(devpoll.close) self.assertEqual(os.get_inheritable(devpoll.fileno()), False) - def test_events_mask_overflow(self): pollster = select.devpoll() w, r = os.pipe() pollster.register(w) # Issue #17919 self.assertRaises(OverflowError, pollster.register, 0, -1) + self.assertRaises(OverflowError, pollster.register, 0, 1 << 64) + self.assertRaises(OverflowError, pollster.modify, 1, -1) + self.assertRaises(OverflowError, pollster.modify, 1, 1 << 64) + + @cpython_only + def test_events_mask_overflow_c_limits(self): + from _testcapi import USHRT_MAX + pollster = select.devpoll() + w, r = os.pipe() + pollster.register(w) + # Issue #17919 self.assertRaises(OverflowError, pollster.register, 0, USHRT_MAX + 1) - self.assertRaises(OverflowError, pollster.modify, 1, -1) self.assertRaises(OverflowError, pollster.modify, 1, USHRT_MAX + 1) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -832,6 +832,7 @@ self.assertIn("maximum recursion depth exceeded", str(v)) + @cpython_only def test_MemoryError(self): # PyErr_NoMemory always raises the same exception instance. # Check that the traceback is not doubled. @@ -890,6 +891,7 @@ self.assertEqual(error5.a, 1) self.assertEqual(error5.__doc__, "") + @cpython_only def test_memory_error_cleanup(self): # Issue #5437: preallocated MemoryError instances should not keep # traceback objects alive. diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -4,9 +4,9 @@ import os import struct import sys -import _testcapi import unittest -from test.support import verbose, TESTFN, unlink, run_unittest, import_module +from test.support import (verbose, TESTFN, unlink, run_unittest, import_module, + cpython_only) # Skip test if no fcntl module. fcntl = import_module('fcntl') @@ -45,6 +45,12 @@ lockdata = get_lockdata() +class BadFile: + def __init__(self, fn): + self.fn = fn + def fileno(self): + return self.fn + class TestFcntl(unittest.TestCase): def setUp(self): @@ -78,24 +84,27 @@ self.f.close() def test_fcntl_bad_file(self): - class F: - def __init__(self, fn): - self.fn = fn - def fileno(self): - return self.fn - self.assertRaises(ValueError, fcntl.fcntl, -1, fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(ValueError, fcntl.fcntl, F(-1), fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(TypeError, fcntl.fcntl, 'spam', fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(TypeError, fcntl.fcntl, F('spam'), fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(ValueError): + fcntl.fcntl(-1, fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(ValueError): + fcntl.fcntl(BadFile(-1), fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(TypeError): + fcntl.fcntl('spam', fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(TypeError): + fcntl.fcntl(BadFile('spam'), fcntl.F_SETFL, os.O_NONBLOCK) + + @cpython_only + def test_fcntl_bad_file_overflow(self): + from _testcapi import INT_MAX, INT_MIN # Issue 15989 - self.assertRaises(OverflowError, fcntl.fcntl, _testcapi.INT_MAX + 1, - fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(OverflowError, fcntl.fcntl, F(_testcapi.INT_MAX + 1), - fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(OverflowError, fcntl.fcntl, _testcapi.INT_MIN - 1, - fcntl.F_SETFL, os.O_NONBLOCK) - self.assertRaises(OverflowError, fcntl.fcntl, F(_testcapi.INT_MIN - 1), - fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(OverflowError): + fcntl.fcntl(INT_MAX + 1, fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(OverflowError): + fcntl.fcntl(BadFile(INT_MAX + 1), fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(OverflowError): + fcntl.fcntl(INT_MIN - 1, fcntl.F_SETFL, os.O_NONBLOCK) + with self.assertRaises(OverflowError): + fcntl.fcntl(BadFile(INT_MIN - 1), fcntl.F_SETFL, os.O_NONBLOCK) @unittest.skipIf( platform.machine().startswith('arm') and platform.system() == 'Linux', @@ -128,6 +137,10 @@ self.assertRaises(ValueError, fcntl.flock, -1, fcntl.LOCK_SH) self.assertRaises(TypeError, fcntl.flock, 'spam', fcntl.LOCK_SH) + + @cpython_only + def test_flock_overflow(self): + import _testcapi self.assertRaises(OverflowError, fcntl.flock, _testcapi.INT_MAX+1, fcntl.LOCK_SH) diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -8,9 +8,8 @@ from array import array from weakref import proxy from functools import wraps -import _testcapi -from test.support import TESTFN, check_warnings, run_unittest, make_bad_fd +from test.support import TESTFN, check_warnings, run_unittest, make_bad_fd, cpython_only from collections import UserList from _io import FileIO as _FileIO @@ -362,7 +361,11 @@ if sys.platform == 'win32': import msvcrt self.assertRaises(OSError, msvcrt.get_osfhandle, make_bad_fd()) + + @cpython_only + def testInvalidFd_overflow(self): # Issue 15989 + import _testcapi self.assertRaises(TypeError, _FileIO, _testcapi.INT_MAX + 1) self.assertRaises(TypeError, _FileIO, _testcapi.INT_MIN - 1) diff --git a/Lib/test/test_finalization.py b/Lib/test/test_finalization.py --- a/Lib/test/test_finalization.py +++ b/Lib/test/test_finalization.py @@ -7,7 +7,15 @@ import unittest import weakref -import _testcapi +try: + from _testcapi import with_tp_del +except ImportError: + def with_tp_del(cls): + class C(object): + def __new__(cls, *args, **kwargs): + raise TypeError('requires _testcapi.with_tp_del') + return C + from test import support @@ -423,11 +431,11 @@ except Exception as e: self.errors.append(e) - at _testcapi.with_tp_del + at with_tp_del class Legacy(LegacyBase): pass - at _testcapi.with_tp_del + at with_tp_del class LegacyResurrector(LegacyBase): def side_effect(self): @@ -436,11 +444,12 @@ """ self.survivors.append(self) - at _testcapi.with_tp_del + at with_tp_del class LegacySelfCycle(SelfCycleBase, LegacyBase): pass + at support.cpython_only class LegacyFinalizationTest(TestBase, unittest.TestCase): """ Test finalization of objects with a tp_del. diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -332,20 +332,29 @@ self.assertIs(text % (), text) self.assertIs(text.format(), text) - @support.cpython_only def test_precision(self): - from _testcapi import INT_MAX - f = 1.2 self.assertEqual(format(f, ".0f"), "1") self.assertEqual(format(f, ".3f"), "1.200") with self.assertRaises(ValueError) as cm: - format(f, ".%sf" % (INT_MAX + 1)) + format(f, ".%sf" % (sys.maxsize + 1)) c = complex(f) self.assertEqual(format(c, ".0f"), "1+0j") self.assertEqual(format(c, ".3f"), "1.200+0.000j") with self.assertRaises(ValueError) as cm: + format(c, ".%sf" % (sys.maxsize + 1)) + + @support.cpython_only + def test_precision_c_limits(self): + from _testcapi import INT_MAX + + f = 1.2 + with self.assertRaises(ValueError) as cm: + format(f, ".%sf" % (INT_MAX + 1)) + + c = complex(f) + with self.assertRaises(ValueError) as cm: format(c, ".%sf" % (INT_MAX + 1)) diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1,7 +1,6 @@ -import _testcapi import unittest from test.support import (verbose, refcount_test, run_unittest, - strip_python_stderr) + strip_python_stderr, cpython_only) from test.script_helper import assert_python_ok, make_script, temp_dir import sys @@ -14,6 +13,15 @@ except ImportError: threading = None +try: + from _testcapi import with_tp_del +except ImportError: + def with_tp_del(cls): + class C(object): + def __new__(cls, *args, **kwargs): + raise TypeError('requires _testcapi.with_tp_del') + return C + ### Support code ############################################################################### @@ -41,7 +49,7 @@ # gc collects it. self.wr = weakref.ref(C1055820(666), it_happened) - at _testcapi.with_tp_del + at with_tp_del class Uncollectable(object): """Create a reference cycle with multiple __del__ methods. @@ -143,10 +151,11 @@ del a self.assertNotEqual(gc.collect(), 0) + @cpython_only def test_legacy_finalizer(self): # A() is uncollectable if it is part of a cycle, make sure it shows up # in gc.garbage. - @_testcapi.with_tp_del + @with_tp_del class A: def __tp_del__(self): pass class B: @@ -168,10 +177,11 @@ self.fail("didn't find obj in garbage (finalizer)") gc.garbage.remove(obj) + @cpython_only def test_legacy_finalizer_newclass(self): # A() is uncollectable if it is part of a cycle, make sure it shows up # in gc.garbage. - @_testcapi.with_tp_del + @with_tp_del class A(object): def __tp_del__(self): pass class B(object): @@ -570,6 +580,7 @@ # would be damaged, with an empty __dict__. self.assertEqual(x, None) + @cpython_only def test_garbage_at_shutdown(self): import subprocess code = """if 1: @@ -764,6 +775,7 @@ info = v[2] self.assertEqual(info["generation"], 2) + @cpython_only def test_collect_garbage(self): self.preclean() # Each of these cause four objects to be garbage: Two diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py --- a/Lib/test/test_getargs2.py +++ b/Lib/test/test_getargs2.py @@ -1,5 +1,7 @@ import unittest from test import support +# Skip this test if the _testcapi module isn't available. +support.import_module('_testcapi') from _testcapi import getargs_keywords, getargs_keyword_only try: from _testcapi import getargs_L, getargs_K diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1,4 +1,3 @@ -import _testcapi import collections import datetime import functools @@ -21,7 +20,7 @@ except ImportError: ThreadPoolExecutor = None -from test.support import run_unittest, TESTFN, DirsOnSysPath +from test.support import run_unittest, TESTFN, DirsOnSysPath, cpython_only from test.support import MISSING_C_DOCSTRINGS from test.script_helper import assert_python_ok, assert_python_failure from test import inspect_fodder as mod @@ -604,16 +603,20 @@ self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, args_e=['self', 'obj'], formatted='(self, obj)') + @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") def test_getfullagrspec_builtin_func(self): + import _testcapi builtin = _testcapi.docstring_with_signature_with_defaults spec = inspect.getfullargspec(builtin) self.assertEqual(spec.defaults[0], 'avocado') + @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") def test_getfullagrspec_builtin_func_no_signature(self): + import _testcapi builtin = _testcapi.docstring_no_signature with self.assertRaises(TypeError): inspect.getfullargspec(builtin) @@ -1647,9 +1650,11 @@ ('kwargs', ..., int, "var_keyword")), ...)) + @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") def test_signature_on_builtins(self): + import _testcapi def test_unbound_method(o): """Use this to test unbound methods (things that should have a self)""" @@ -1709,9 +1714,11 @@ __call__ = type test_callable(ThisWorksNow()) + @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") def test_signature_on_decorated_builtins(self): + import _testcapi func = _testcapi.docstring_with_signature_with_defaults def decorator(func): @@ -1725,7 +1732,9 @@ self.assertEqual(inspect.signature(func), inspect.signature(decorated_func)) + @cpython_only def test_signature_on_builtins_no_signature(self): + import _testcapi with self.assertRaisesRegex(ValueError, 'no signature found for builtin'): inspect.signature(_testcapi.docstring_no_signature) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -32,7 +32,6 @@ import unittest import warnings import weakref -import _testcapi from collections import deque, UserList from itertools import cycle, count from test import support @@ -1997,8 +1996,10 @@ os.environ.clear() os.environ.update(old_environ) - # Issue 15989 + @support.cpython_only def test_device_encoding(self): + # Issue 15989 + import _testcapi b = self.BytesIO() b.fileno = lambda: _testcapi.INT_MAX + 1 self.assertRaises(OverflowError, self.TextIOWrapper, b) diff --git a/Lib/test/test_poll.py b/Lib/test/test_poll.py --- a/Lib/test/test_poll.py +++ b/Lib/test/test_poll.py @@ -4,14 +4,13 @@ import subprocess import random import select -from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX try: import threading except ImportError: threading = None import time import unittest -from test.support import TESTFN, run_unittest, reap_threads +from test.support import TESTFN, run_unittest, reap_threads, cpython_only try: select.poll @@ -163,8 +162,18 @@ # Issues #15989, #17919 self.assertRaises(OverflowError, pollster.register, 0, -1) + self.assertRaises(OverflowError, pollster.register, 0, 1 << 64) + self.assertRaises(OverflowError, pollster.modify, 1, -1) + self.assertRaises(OverflowError, pollster.modify, 1, 1 << 64) + + @cpython_only + def test_poll_c_limits(self): + from _testcapi import USHRT_MAX, INT_MAX, UINT_MAX + pollster = select.poll() + pollster.register(1) + + # Issues #15989, #17919 self.assertRaises(OverflowError, pollster.register, 0, USHRT_MAX + 1) - self.assertRaises(OverflowError, pollster.modify, 1, -1) self.assertRaises(OverflowError, pollster.modify, 1, USHRT_MAX + 1) self.assertRaises(OverflowError, pollster.poll, INT_MAX + 1) self.assertRaises(OverflowError, pollster.poll, UINT_MAX + 1) diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -17,7 +17,6 @@ import tempfile import unittest import warnings -import _testcapi _DUMMY_SYMLINK = os.path.join(tempfile.gettempdir(), support.TESTFN + '-dummy-symlink') @@ -617,7 +616,12 @@ except OSError: pass + @support.cpython_only + @unittest.skipUnless(hasattr(os, 'pipe2'), "test needs os.pipe2()") + @support.requires_linux_version(2, 6, 27) + def test_pipe2_c_limits(self): # Issue 15989 + import _testcapi self.assertRaises(OverflowError, os.pipe2, _testcapi.INT_MAX + 1) self.assertRaises(OverflowError, os.pipe2, _testcapi.UINT_MAX + 1) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -6,7 +6,6 @@ import socket import select import tempfile -import _testcapi import time import traceback import queue @@ -1344,7 +1343,10 @@ srv.listen(backlog) srv.close() + @support.cpython_only + def test_listen_backlog_overflow(self): # Issue 15989 + import _testcapi srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.bind((HOST, 0)) self.assertRaises(OverflowError, srv.listen, _testcapi.INT_MAX + 1) @@ -1738,6 +1740,14 @@ def _testShutdown(self): self.serv_conn.send(MSG) + self.serv_conn.shutdown(2) + + testShutdown_overflow = support.cpython_only(testShutdown) + + @support.cpython_only + def _testShutdown_overflow(self): + import _testcapi + self.serv_conn.send(MSG) # Issue 15989 self.assertRaises(OverflowError, self.serv_conn.shutdown, _testcapi.INT_MAX + 1) @@ -2506,7 +2516,12 @@ # code with these functions. # Match the definition in socketmodule.c - socklen_t_limit = min(0x7fffffff, _testcapi.INT_MAX) + try: + import _testcapi + except ImportError: + socklen_t_limit = 0x7fffffff + else: + socklen_t_limit = min(0x7fffffff, _testcapi.INT_MAX) @requireAttrs(socket, "CMSG_LEN") def testCMSG_LEN(self): @@ -3731,14 +3746,23 @@ pass end = time.time() self.assertTrue((end - start) < 1.0, "Error setting non-blocking mode.") - # Issue 15989 - if _testcapi.UINT_MAX < _testcapi.ULONG_MAX: - self.serv.setblocking(_testcapi.UINT_MAX + 1) - self.assertIsNone(self.serv.gettimeout()) def _testSetBlocking(self): pass + @support.cpython_only + def testSetBlocking_overflow(self): + # Issue 15989 + import _testcapi + if _testcapi.UINT_MAX >= _testcapi.ULONG_MAX: + self.skipTest('needs UINT_MAX < ULONG_MAX') + self.serv.setblocking(False) + self.assertEqual(self.serv.gettimeout(), 0.0) + self.serv.setblocking(_testcapi.UINT_MAX + 1) + self.assertIsNone(self.serv.gettimeout()) + + _testSetBlocking_overflow = support.cpython_only(_testSetBlocking) + @unittest.skipUnless(hasattr(socket, 'SOCK_NONBLOCK'), 'test needs socket.SOCK_NONBLOCK') @support.requires_linux_version(2, 6, 28) diff --git a/Lib/test/test_structmembers.py b/Lib/test/test_structmembers.py --- a/Lib/test/test_structmembers.py +++ b/Lib/test/test_structmembers.py @@ -1,3 +1,8 @@ +import unittest +from test import support + +# Skip this test if the _testcapi module isn't available. +support.import_module('_testcapi') from _testcapi import _test_structmembersType, \ CHAR_MAX, CHAR_MIN, UCHAR_MAX, \ SHRT_MAX, SHRT_MIN, USHRT_MAX, \ @@ -6,9 +11,6 @@ LLONG_MAX, LLONG_MIN, ULLONG_MAX, \ PY_SSIZE_T_MAX, PY_SSIZE_T_MIN -import unittest -from test import support - ts=_test_structmembersType(False, # T_BOOL 1, # T_BYTE 2, # T_UBYTE diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -698,6 +698,7 @@ self.assertIn(c, range(b - 50, b + 50)) + at test.support.cpython_only class SizeofTest(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -1,7 +1,6 @@ import unittest import sys import os -import _testcapi from test import support # Skip this test if the _tkinter module wasn't built. @@ -13,6 +12,11 @@ from tkinter import Tcl from _tkinter import TclError +try: + from _testcapi import INT_MAX, PY_SSIZE_T_MAX +except ImportError: + INT_MAX = PY_SSIZE_T_MAX = sys.maxsize + tcl_version = _tkinter.TCL_VERSION.split('.') try: for i in range(len(tcl_version)): @@ -505,9 +509,9 @@ def setUp(self): self.interp = Tcl() - @unittest.skipUnless(_testcapi.INT_MAX < _testcapi.PY_SSIZE_T_MAX, - "needs UINT_MAX < SIZE_MAX") - @support.bigmemtest(size=_testcapi.INT_MAX + 1, memuse=5, dry_run=False) + @support.cpython_only + @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX") + @support.bigmemtest(size=INT_MAX + 1, memuse=5, dry_run=False) def test_huge_string(self, size): value = ' ' * size self.assertRaises(OverflowError, self.interp.call, 'set', '_', value) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -3,7 +3,7 @@ """ import test.support -from test.support import verbose, strip_python_stderr, import_module +from test.support import verbose, strip_python_stderr, import_module, cpython_only from test.script_helper import assert_python_ok import random @@ -11,7 +11,6 @@ import sys _thread = import_module('_thread') threading = import_module('threading') -import _testcapi import time import unittest import weakref @@ -662,6 +661,7 @@ self.assertRegex(err.rstrip(), b"^sys:1: ResourceWarning: unclosed file ") + @cpython_only def test_frame_tstate_tracing(self): # Issue #14432: Crash when a generator is created in a C thread that is # destroyed while the generator is still used. The issue was that a @@ -690,6 +690,7 @@ threading.settrace(noop_trace) # Create a generator in a C thread which exits after the call + import _testcapi _testcapi.call_in_temporary_c_thread(callback) # Call the generator in a different Python thread, check that the @@ -928,6 +929,7 @@ # The thread was joined properly. self.assertEqual(os.read(r, 1), b"x") + @cpython_only def test_daemon_threads_fatal_error(self): subinterp_code = r"""if 1: import os diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -582,6 +582,7 @@ -(2.0 ** 100.0), 2.0 ** 100.0, ) + @support.cpython_only def test_time_t(self): from _testcapi import pytime_object_to_time_t for obj, time_t in ( @@ -597,6 +598,7 @@ for invalid in self.invalid_values: self.assertRaises(OverflowError, pytime_object_to_time_t, invalid) + @support.cpython_only def test_timeval(self): from _testcapi import pytime_object_to_timeval for obj, timeval in ( @@ -616,6 +618,7 @@ for invalid in self.invalid_values: self.assertRaises(OverflowError, pytime_object_to_timeval, invalid) + @support.cpython_only def test_timespec(self): from _testcapi import pytime_object_to_timespec for obj, timespec in ( diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -1,12 +1,11 @@ """Test cases for traceback module""" -from _testcapi import traceback_print, exception_print from io import StringIO import sys import unittest import re from test.support import run_unittest, Error, captured_output -from test.support import TESTFN, unlink +from test.support import TESTFN, unlink, cpython_only import traceback @@ -176,7 +175,9 @@ def some_exception(self): raise KeyError('blah') + @cpython_only def check_traceback_format(self, cleanup_func=None): + from _testcapi import traceback_print try: self.some_exception() except KeyError: @@ -404,7 +405,9 @@ # This checks built-in reporting by the interpreter. # + @cpython_only def get_report(self, e): + from _testcapi import exception_print e = self.get_exception(e) with captured_output("stderr") as s: exception_print(e) diff --git a/Lib/test/test_ucn.py b/Lib/test/test_ucn.py --- a/Lib/test/test_ucn.py +++ b/Lib/test/test_ucn.py @@ -9,12 +9,16 @@ import unittest import unicodedata -import _testcapi from test import support from http.client import HTTPException from test.test_normalization import check_version +try: + from _testcapi import INT_MAX, PY_SSIZE_T_MAX, UINT_MAX +except ImportError: + INT_MAX = PY_SSIZE_T_MAX = UINT_MAX = 2**64 - 1 + class UnicodeNamesTest(unittest.TestCase): def checkletter(self, name, code): @@ -216,15 +220,13 @@ str, b"\\NSPACE", 'unicode-escape', 'strict' ) - @unittest.skipUnless(_testcapi.INT_MAX < _testcapi.PY_SSIZE_T_MAX, - "needs UINT_MAX < SIZE_MAX") - @support.bigmemtest(size=_testcapi.UINT_MAX + 1, - memuse=2 + 1, dry_run=False) + @support.cpython_only + @unittest.skipUnless(INT_MAX < PY_SSIZE_T_MAX, "needs UINT_MAX < SIZE_MAX") + @support.bigmemtest(size=UINT_MAX + 1, memuse=2 + 1, dry_run=False) def test_issue16335(self, size): # very very long bogus character name - x = b'\\N{SPACE' + b'x' * (_testcapi.UINT_MAX + 1) + b'}' - self.assertEqual(len(x), len(b'\\N{SPACE}') + - (_testcapi.UINT_MAX + 1)) + x = b'\\N{SPACE' + b'x' * (UINT_MAX + 1) + b'}' + self.assertEqual(len(x), len(b'\\N{SPACE}') + (UINT_MAX + 1)) self.assertRaisesRegex(UnicodeError, 'unknown Unicode character name', x.decode, 'unicode-escape' diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -1187,8 +1187,13 @@ self.assertEqual('...%(foo)f...' % {'foo':Float.PI,'def':123}, '...3.141593...') + def test_formatting_huge_precision(self): + format_string = "%.{}f".format(sys.maxsize + 1) + with self.assertRaises(ValueError): + result = format_string % 2.34 + @support.cpython_only - def test_formatting_huge_precision(self): + def test_formatting_huge_precision_c_limits(self): from _testcapi import INT_MAX format_string = "%.{}f".format(INT_MAX + 1) with self.assertRaises(ValueError): @@ -2315,6 +2320,7 @@ b'%.%s', b'abc') # Test PyUnicode_AsWideChar() + @support.cpython_only def test_aswidechar(self): from _testcapi import unicode_aswidechar support.import_module('ctypes') @@ -2352,6 +2358,7 @@ self.assertEqual(wchar, nonbmp + '\0') # Test PyUnicode_AsWideCharString() + @support.cpython_only def test_aswidecharstring(self): from _testcapi import unicode_aswidecharstring support.import_module('ctypes') @@ -2386,6 +2393,7 @@ s += "4" self.assertEqual(s, "3") + @support.cpython_only def test_encode_decimal(self): from _testcapi import unicode_encodedecimal self.assertEqual(unicode_encodedecimal('123'), @@ -2401,6 +2409,7 @@ "^'decimal' codec can't encode character", unicode_encodedecimal, "123\u20ac", "replace") + @support.cpython_only def test_transform_decimal(self): from _testcapi import unicode_transformdecimaltoascii as transform_decimal self.assertEqual(transform_decimal('123'), diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -125,6 +125,8 @@ Tests ----- +- Issue #20532: Tests which use _testcapi now are marked as CPython only. + - Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. - Issue #19990: Added tests for the imghdr module. Based on patch by -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 13:28:34 2014 From: python-checkins at python.org (nick.coghlan) Date: Fri, 7 Feb 2014 13:28:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320053=3A_Actually?= =?utf-8?q?_test_relevant_assumption?= Message-ID: <3fLG5G70cXzQPM@mail.python.org> http://hg.python.org/cpython/rev/17bea44a9fa7 changeset: 89010:17bea44a9fa7 user: Nick Coghlan date: Fri Feb 07 22:28:18 2014 +1000 summary: Issue #20053: Actually test relevant assumption files: Lib/test/test_venv.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -291,7 +291,7 @@ def test_devnull_exists_and_is_empty(self): # Fix for issue #20053 uses os.devnull to force a config file to # appear empty. Make sure that assumption is valid cross platform. - self.assertTrue(os.path.exists, os.devnull) + self.assertTrue(os.path.exists(os.devnull)) with open(os.devnull, "rb") as f: self.assertEqual(f.read(), b"") -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 14:35:03 2014 From: python-checkins at python.org (nick.coghlan) Date: Fri, 7 Feb 2014 14:35:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_20542=3A_Temporarily?= =?utf-8?q?_skip_failing_test?= Message-ID: <3fLHYz5L9Lz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/2e7c46718b83 changeset: 89011:2e7c46718b83 user: Nick Coghlan date: Fri Feb 07 23:34:41 2014 +1000 summary: Issue 20542: Temporarily skip failing test files: Lib/test/test_codecs.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -124,6 +124,8 @@ "".join(codecs.iterdecode([bytes([c]) for c in encoded], self.encoding)) ) + # Temporary skip, see http://bugs.python.org/issue20542 + @unittest.skip def test_readline(self): def getreader(input): stream = io.BytesIO(input.encode(self.encoding)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 14:46:50 2014 From: python-checkins at python.org (nick.coghlan) Date: Fri, 7 Feb 2014 14:46:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320053=3A_Mark_as_?= =?utf-8?q?an_expected_failure_for_3=2E4?= Message-ID: <3fLHqZ5RSxz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/f3f92d55f942 changeset: 89012:f3f92d55f942 user: Nick Coghlan date: Fri Feb 07 23:46:38 2014 +1000 summary: Issue #20053: Mark as an expected failure for 3.4 files: Lib/test/test_venv.py | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -28,6 +28,12 @@ skipInVenv = unittest.skipIf(sys.prefix != sys.base_prefix, 'Test not appropriate in a venv') +# os.path.exists('nul') is False: http://bugs.python.org/issue20541 +if os.devnull.lower() == 'nul': + failsOnWindows = unittest.expectedFailure +else: + def failsOnWindows(f): + return f class BaseTest(unittest.TestCase): """Base class for venv tests.""" @@ -288,9 +294,12 @@ self.run_with_capture(venv.create, self.env_dir, with_pip=False) self.assert_pip_not_installed() + @failsOnWindows def test_devnull_exists_and_is_empty(self): # Fix for issue #20053 uses os.devnull to force a config file to - # appear empty. Make sure that assumption is valid cross platform. + # appear empty. However http://bugs.python.org/issue20541 means + # that doesn't currently work properly on Windows. Once that is + # fixed, the "win_location" part of test_with_pip should be restored self.assertTrue(os.path.exists(os.devnull)) with open(os.devnull, "rb") as f: self.assertEqual(f.read(), b"") @@ -319,7 +328,8 @@ # cross-platform variation in test code behaviour win_location = ("pip", "pip.ini") posix_location = (".pip", "pip.conf") - for dirname, fname in (win_location, posix_location): + # Skips win_location due to http://bugs.python.org/issue20541 + for dirname, fname in (posix_location,): dirpath = os.path.join(home_dir, dirname) os.mkdir(dirpath) fpath = os.path.join(dirpath, fname) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 16:44:48 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 16:44:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2320476=3A_use_EmailMessa?= =?utf-8?q?ge_as_factory_if_non-compat32_policy_is_used=2E?= Message-ID: <3fLLRh6wpRz7LkD@mail.python.org> http://hg.python.org/cpython/rev/77082b818676 changeset: 89013:77082b818676 user: R David Murray date: Fri Feb 07 10:44:16 2014 -0500 summary: #20476: use EmailMessage as factory if non-compat32 policy is used. In 3.5 I will fix this right by adding a message_factory attribute to the policy. files: Lib/email/feedparser.py | 25 +++++++++++----- Lib/email/parser.py | 2 +- Lib/test/test_email/test_message.py | 16 ++++++++++- Misc/NEWS | 4 ++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Lib/email/feedparser.py b/Lib/email/feedparser.py --- a/Lib/email/feedparser.py +++ b/Lib/email/feedparser.py @@ -126,7 +126,7 @@ class FeedParser: """A feed-style parser of email.""" - def __init__(self, _factory=message.Message, *, policy=compat32): + def __init__(self, _factory=None, *, policy=compat32): """_factory is called with no arguments to create a new message obj The policy keyword specifies a policy object that controls a number of @@ -134,14 +134,23 @@ backward compatibility. """ - self._factory = _factory self.policy = policy - try: - _factory(policy=self.policy) - self._factory_kwds = lambda: {'policy': self.policy} - except TypeError: - # Assume this is an old-style factory - self._factory_kwds = lambda: {} + self._factory_kwds = lambda: {'policy': self.policy} + if _factory is None: + # What this should be: + #self._factory = policy.default_message_factory + # but, because we are post 3.4 feature freeze, fix with temp hack: + if self.policy is compat32: + self._factory = message.Message + else: + self._factory = message.EmailMessage + else: + self._factory = _factory + try: + _factory(policy=self.policy) + except TypeError: + # Assume this is an old-style factory + self._factory_kwds = lambda: {} self._input = BufferedSubFile() self._msgstack = [] self._parse = self._parsegen().__next__ diff --git a/Lib/email/parser.py b/Lib/email/parser.py --- a/Lib/email/parser.py +++ b/Lib/email/parser.py @@ -17,7 +17,7 @@ class Parser: - def __init__(self, _class=Message, *, policy=compat32): + def __init__(self, _class=None, *, policy=compat32): """Parser of RFC 2822 and MIME email messages. Creates an in-memory object tree representing the email message, which diff --git a/Lib/test/test_email/test_message.py b/Lib/test/test_email/test_message.py --- a/Lib/test/test_email/test_message.py +++ b/Lib/test/test_email/test_message.py @@ -1,6 +1,6 @@ import unittest import textwrap -from email import policy +from email import policy, message_from_string from email.message import EmailMessage, MIMEPart from test.test_email import TestEmailBase, parameterize @@ -20,6 +20,20 @@ with self.assertRaises(ValueError): m['To'] = 'xyz at abc' + def test_rfc2043_auto_decoded_and_emailmessage_used(self): + m = message_from_string(textwrap.dedent("""\ + Subject: Ayons asperges pour le =?utf-8?q?d=C3=A9jeuner?= + From: =?utf-8?q?Pep=C3=A9?= Le Pew + To: "Penelope Pussycat" <"penelope at example.com"> + MIME-Version: 1.0 + Content-Type: text/plain; charset="utf-8" + + sample text + """), policy=policy.default) + self.assertEqual(m['subject'], "Ayons asperges pour le d?jeuner") + self.assertEqual(m['from'], "Pep? Le Pew ") + self.assertIsInstance(m, EmailMessage) + @parameterize class TestEmailMessageBase: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,10 @@ Library ------- +- Issue #20476: If a non-compat32 policy is used with any of the email parsers, + EmailMessage is now used as the factory class. The factory class should + really come from the policy; that will get fixed in 3.5. + - Issue #19920: TarFile.list() no longer fails when outputs a listing containing non-encodable characters. Based on patch by Vajrasky Kok. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 16:55:33 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 16:55:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2320477=3A_add_examples_o?= =?utf-8?q?f_using_the_new_contentmanager_API=2E?= Message-ID: <3fLLh55nTnz7LjN@mail.python.org> http://hg.python.org/cpython/rev/a9d7d53d5fbd changeset: 89014:a9d7d53d5fbd user: R David Murray date: Fri Feb 07 10:55:17 2014 -0500 summary: #20477: add examples of using the new contentmanager API. files: Doc/includes/email-alternative-new-api.py | 56 +++++++ Doc/includes/email-read-alternative-new-api.py | 74 ++++++++++ Doc/library/email-examples.rst | 28 +++ 3 files changed, 158 insertions(+), 0 deletions(-) diff --git a/Doc/includes/email-alternative-new-api.py b/Doc/includes/email-alternative-new-api.py new file mode 100644 --- /dev/null +++ b/Doc/includes/email-alternative-new-api.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +import smtplib + +from email.message import EmailMessage +from email.headerregistry import Address +from email.utils import make_msgid + +# Create the base text message. +msg = EmailMessage() +msg['Subject'] = "Ayons asperges pour le d?jeuner" +msg['From'] = Address("Pep? Le Pew", "pepe at example.com") +msg['To'] = (Address("Penelope Pussycat", "penelope at example.com"), + Address("Fabrette Pussycat", "fabrette at example.com")) +msg.set_content("""\ +Salut! + +Cela ressemble ? un excellent recipie[1] d?jeuner. + +[1] http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718 + +--?ric +""") + +# Add the html version. This converts the message into a multipart/alternative +# container, with the original text message as the first part and the new html +# message as the second part. +asparagus_cid = make_msgid() +msg.add_alternative("""\ + + + +

Salut!<\p> +

Cela ressemble ? un excellent + + + +""".format(asparagus_cid=asparagus_cid[1:-1]), subtype='html') +# note that we needed to peel the <> off the msgid for use in the html. + +# Now add the related image to the html part. +with open("roasted-asparagus.jpg", 'rb') as img: + msg.get_payload()[1].add_related(img.read(), 'image', 'jpeg', + cid=asparagus_cid) + +# Make a local copy of what we are going to send. +with open('outgoing.msg', 'wb') as f: + f.write(bytes(msg)) + +# Send the message via local SMTP server. +with smtplib.SMTP('localhost') as s: + s.send_message(msg) diff --git a/Doc/includes/email-read-alternative-new-api.py b/Doc/includes/email-read-alternative-new-api.py new file mode 100644 --- /dev/null +++ b/Doc/includes/email-read-alternative-new-api.py @@ -0,0 +1,74 @@ +import os +import sys +import tempfile +import mimetypes +import webbrowser + +# Import the email modules we'll need +from email import policy +from email.parser import BytesParser + +# An imaginary module that would make this work and be safe. +from imaginary import magic_html_parser + +# In a real program you'd get the filename from the arguments. +msg = BytesParser(policy=policy.default).parse(open('outgoing.msg', 'rb')) + +# Now the header items can be accessed as a dictionary, and any non-ASCII will +# be converted to unicode: +print('To:', msg['to']) +print('From:', msg['from']) +print('Subject:', msg['subject']) + +# If we want to print a priview 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. +simplest = msg.get_body(preferencelist=('plain', 'html')) +print() +print(''.join(simplest.get_content().splitlines(keepends=True)[:3])) + +ans = input("View full message?") +if ans.lower()[0] == 'n': + sys.exit() + +# We can extract the richest alternative in order to display it: +richest = msg.get_body() +partfiles = {} +if richest['content-type'].maintype == 'text': + if richest['content-type'].subtype == 'plain': + for line in richest.get_content().splitlines(): + print(line) + sys.exit() + elif richest['content-type'].subtype == 'html': + body = richest + else: + print("Don't know how to display {}".format(richest.get_content_type())) + sys.exit() +elif richest['content-type'].content_type == 'multipart/related': + body = richest.get_body(preferencelist=('html')) + for part in richest.iter_attachments(): + fn = part.get_filename() + if fn: + extension = os.path.splitext(part.get_filename())[1] + else: + extension = mimetypes.guess_extension(part.get_content_type()) + with tempfile.NamedTemporaryFile(suffix=extension, delete=False) as f: + f.write(part.get_content()) + # again strip the <> to go from email form of cid to html form. + partfiles[part['content-id'][1:-1]] = f.name +else: + print("Don't know how to display {}".format(richest.get_content_type())) + sys.exit() +with tempfile.NamedTemporaryFile(mode='w', delete=False) as f: + # The magic_html_parser has to rewrite the href="cid:...." attributes to + # point to the filenames in partfiles. It also has to do a safety-sanitize + # of the html. It could be written using html.parser. + f.write(magic_html_parser(body.get_content(), partfiles)) +webbrowser.open(f.name) +os.remove(f.name) +for fn in partfiles.values(): + os.remove(fn) + +# Of course, there are lots of email messages that could break this simple +# minded program, but it will handle the most common ones. diff --git a/Doc/library/email-examples.rst b/Doc/library/email-examples.rst --- a/Doc/library/email-examples.rst +++ b/Doc/library/email-examples.rst @@ -40,6 +40,34 @@ .. literalinclude:: ../includes/email-alternative.py +Examples using the Provision API +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Here is a reworking of the last example using the provisional API. To make +things a bit more interesting, we include a related image in the html part, and +we save a copy of what we are going to send to disk, as well as sending it. + +This example also shows how easy it is to include non-ASCII, and simplifies the +sending of the message using the :meth:`.send_message` method of the +:mod:`smtplib` module. + +.. literalinclude:: ../includes/email-alternative-new-api.py + +If we were instead sent the message from the last example, here is one +way we could process it: + +.. literalinclude:: ../includes/email-read-alternative-new-api.py + +Up to the prompt, the output from the above is:: + + To: Penelope Pussycat <"penelope at example.com">, Fabrette Pussycat <"fabrette at example.com"> + From: Pep? Le Pew + Subject: Ayons asperges pour le d?jeuner + + Salut! + + Cela ressemble ? un excellent recipie[1] d?jeuner. + + .. rubric:: Footnotes .. [1] Thanks to Matthew Dixon Cowles for the original inspiration and examples. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 17:57:59 2014 From: python-checkins at python.org (victor.stinner) Date: Fri, 7 Feb 2014 17:57:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320505=3A_add_debu?= =?utf-8?q?g_info?= Message-ID: <3fLN473D7vz7Lk9@mail.python.org> http://hg.python.org/cpython/rev/3b94a4ef244e changeset: 89015:3b94a4ef244e user: Victor Stinner date: Fri Feb 07 17:53:13 2014 +0100 summary: Issue #20505: add debug info files: Lib/asyncio/base_events.py | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -634,7 +634,17 @@ else: logger.log(level, 'poll took %.3f seconds', t1-t0) else: + t0 = self.time() event_list = self._selector.select(timeout) + dt = self.time() - t0 + if timeout and not event_list and dt < timeout: + print("%s.select(%.3f ms) took %.3f ms (granularity=%.3f ms, resolution=%.3f ms)" + % (self._selector.__class__.__name__, + timeout * 1e3, + dt * 1e3, + self._granularity * 1e3, + self._selector.resolution * 1e3), + file=sys.__stderr__) self._process_events(event_list) # Handle 'later' callbacks that are ready. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 19:03:17 2014 From: python-checkins at python.org (victor.stinner) Date: Fri, 7 Feb 2014 19:03:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_mention_tha?= =?utf-8?q?t_asyncio_is_not_thread-safe?= Message-ID: <3fLPWT6CFRz7LkC@mail.python.org> http://hg.python.org/cpython/rev/86bc4194f986 changeset: 89016:86bc4194f986 user: Victor Stinner date: Fri Feb 07 19:03:05 2014 +0100 summary: asyncio doc: mention that asyncio is not thread-safe files: Doc/library/asyncio-dev.rst | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -23,6 +23,12 @@ loop.call_soon_threadsafe(asyncio.async, coro_func()) +Most asyncio objects are not thread safe. You should only worry if you access +objects outside the event loop. For example, to cancel a future, don't call +directly its :meth:`Future.cancel` method, but:: + + loop.call_soon_threadsafe(fut.cancel) + To handle signals and to execute subprocesses, the event loop must be run in the main thread. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 19:06:36 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 19:06:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE5MDYzOiB0aGUg?= =?utf-8?q?unicode-in-set=5Fpayload_problem_isn=27t_getting_fixed_in_3=2E4?= =?utf-8?q?=2E?= Message-ID: <3fLPbJ3cWWz7LkV@mail.python.org> http://hg.python.org/cpython/rev/4daf3cec9419 changeset: 89017:4daf3cec9419 branch: 3.3 parent: 89008:e5a78f7c2dcb user: R David Murray date: Fri Feb 07 13:03:08 2014 -0500 summary: #19063: the unicode-in-set_payload problem isn't getting fixed in 3.4. files: Lib/email/message.py | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Lib/email/message.py b/Lib/email/message.py --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -277,8 +277,6 @@ """ if hasattr(payload, 'encode'): if charset is None: - # We should check for ASCII-only here, but we can't do that - # for backward compatibility reasons. Fixed in 3.4. self._payload = payload return if not isinstance(charset, Charset): @@ -326,8 +324,9 @@ try: cte(self) except TypeError: - # This if is for backward compatibility and will be removed - # in 3.4 when the ascii check is added to set_payload. + # This 'if' is for backward compatibility, it allows unicode + # through even though that won't work correctly if the + # message is serialized. payload = self._payload if payload: try: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 19:06:37 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 19:06:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2320531=3A_Revert_e20f98a?= =?utf-8?q?8ed71=2C_the_3=2E4_version_of_the_=2319063_fix=2E?= Message-ID: <3fLPbK6gYXz7Lm3@mail.python.org> http://hg.python.org/cpython/rev/f942f1eddfea changeset: 89018:f942f1eddfea parent: 89016:86bc4194f986 user: R David Murray date: Fri Feb 07 12:40:37 2014 -0500 summary: #20531: Revert e20f98a8ed71, the 3.4 version of the #19063 fix. files: Doc/library/email.message.rst | 8 +- Lib/email/charset.py | 29 +++-- Lib/email/message.py | 22 +--- Lib/test/test_email/test_contentmanager.py | 5 +- Lib/test/test_email/test_email.py | 52 ++------- 5 files changed, 38 insertions(+), 78 deletions(-) diff --git a/Doc/library/email.message.rst b/Doc/library/email.message.rst --- a/Doc/library/email.message.rst +++ b/Doc/library/email.message.rst @@ -196,13 +196,7 @@ Set the entire message object's payload to *payload*. It is the client's responsibility to ensure the payload invariants. Optional *charset* sets - the message's character set; see :meth:`set_charset` for details. If - *payload* is a string containing non-ASCII characters, *charset* is - required. - - .. versionchanged:: 3.4 - Previous to 3.4 *charset* was not required when *payload* was a - non-ASCII string, but omitting it produced nonsense results. + the message's default character set; see :meth:`set_charset` for details. .. method:: set_charset(charset) diff --git a/Lib/email/charset.py b/Lib/email/charset.py --- a/Lib/email/charset.py +++ b/Lib/email/charset.py @@ -378,19 +378,18 @@ return None def body_encode(self, string): - """Body-encode a string, converting it first to bytes if needed. + """Body-encode a string by converting it first to bytes. The type of encoding (base64 or quoted-printable) will be based on - self.body_encoding. If body_encoding is None, we perform no CTE - encoding (the CTE will be either 7bit or 8bit), we just encode the - binary representation to ascii using the surrogateescape error handler, - which will enable the Generators to produce the correct output. + self.body_encoding. If body_encoding is None, we assume the + output charset is a 7bit encoding, so re-encoding the decoded + string using the ascii codec produces the correct string version + of the content. """ - if not string: - return string - if isinstance(string, str): - string = string.encode(self.output_charset) + # 7bit/8bit encodings return the string unchanged (module conversions) if self.body_encoding is BASE64: + if isinstance(string, str): + string = string.encode(self.output_charset) return email.base64mime.body_encode(string) elif self.body_encoding is QP: # quopromime.body_encode takes a string, but operates on it as if @@ -399,7 +398,15 @@ # character set, then, we must turn it into pseudo bytes via the # latin1 charset, which will encode any byte as a single code point # between 0 and 255, which is what body_encode is expecting. - string = string.decode('latin1') + # + # Note that this clause doesn't handle the case of a _payload that + # is already bytes. It never did, and the semantics of _payload + # being bytes has never been nailed down, so fixing that is a + # longer term TODO. + if isinstance(string, str): + string = string.encode(self.output_charset).decode('latin1') return email.quoprimime.body_encode(string) else: - return string.decode('ascii', 'surrogateescape') + if isinstance(string, str): + string = string.encode(self.output_charset).decode('ascii') + return string diff --git a/Lib/email/message.py b/Lib/email/message.py --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -301,23 +301,9 @@ Optional charset sets the message's default character set. See set_charset() for details. """ - if hasattr(payload, 'encode'): - if charset is None: - try: - payload.encode('ascii', 'surrogateescape') - except UnicodeError: - raise TypeError("charset argument must be specified" - " when non-ASCII characters are used in the" - " payload") from None - self._payload = payload - return - if not isinstance(charset, Charset): - charset = Charset(charset) - payload = payload.encode(charset.output_charset) - if hasattr(payload, 'decode'): - self._payload = payload.decode('ascii', 'surrogateescape') - else: - self._payload = payload + if isinstance(payload, bytes): + payload = payload.decode('ascii', 'surrogateescape') + self._payload = payload if charset is not None: self.set_charset(charset) @@ -356,7 +342,7 @@ try: cte(self) except TypeError: - self._payload = charset.body_encode(self.get_payload(decode=True)) + self._payload = charset.body_encode(self._payload) self.add_header('Content-Transfer-Encoding', cte) def get_charset(self): diff --git a/Lib/test/test_email/test_contentmanager.py b/Lib/test/test_email/test_contentmanager.py --- a/Lib/test/test_email/test_contentmanager.py +++ b/Lib/test/test_email/test_contentmanager.py @@ -208,11 +208,12 @@ "Bas?c t?xt.\n") def test_get_text_plain_utf8_base64_recoverable_bad_CTE_data(self): - m = self._bytes_msg(textwrap.dedent("""\ + m = self._str_msg(textwrap.dedent("""\ Content-Type: text/plain; charset="utf8" Content-Transfer-Encoding: base64 - QmFzw6xjIHTDq3h0Lgo""").encode('ascii') + b'\xFF=\n') + QmFzw6xjIHTDq3h0Lgo\xFF= + """)) self.assertEqual(raw_data_manager.get_content(m, errors='ignore'), "Bas?c t?xt.\n") diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -92,44 +92,6 @@ msg.set_payload('This is a string payload', charset) self.assertEqual(msg.get_charset().input_charset, 'iso-8859-1') - def test_set_payload_with_8bit_data_and_charset(self): - data = b'\xd0\x90\xd0\x91\xd0\x92' - charset = Charset('utf-8') - msg = Message() - msg.set_payload(data, charset) - self.assertEqual(msg['content-transfer-encoding'], 'base64') - self.assertEqual(msg.get_payload(decode=True), data) - self.assertEqual(msg.get_payload(), '0JDQkdCS\n') - - def test_set_payload_with_non_ascii_and_charset_body_encoding_none(self): - data = b'\xd0\x90\xd0\x91\xd0\x92' - charset = Charset('utf-8') - charset.body_encoding = None # Disable base64 encoding - msg = Message() - msg.set_payload(data.decode('utf-8'), charset) - self.assertEqual(msg['content-transfer-encoding'], '8bit') - self.assertEqual(msg.get_payload(decode=True), data) - - def test_set_payload_with_8bit_data_and_charset_body_encoding_none(self): - data = b'\xd0\x90\xd0\x91\xd0\x92' - charset = Charset('utf-8') - charset.body_encoding = None # Disable base64 encoding - msg = Message() - msg.set_payload(data, charset) - self.assertEqual(msg['content-transfer-encoding'], '8bit') - self.assertEqual(msg.get_payload(decode=True), data) - - def test_set_payload_to_list(self): - msg = Message() - msg.set_payload([]) - self.assertEqual(msg.get_payload(), []) - - def test_set_payload_with_non_ascii_and_no_charset_raises(self): - data = b'\xd0\x90\xd0\x91\xd0\x92'.decode('utf-8') - msg = Message() - with self.assertRaises(TypeError): - msg.set_payload(data) - def test_get_charsets(self): eq = self.assertEqual @@ -596,10 +558,20 @@ self.assertIsInstance(msg.defects[0], errors.InvalidBase64CharactersDefect) + def test_broken_unicode_payload(self): + # This test improves coverage but is not a compliance test. + # The behavior in this situation is currently undefined by the API. + x = 'this is a br\xf6ken thing to do' + msg = Message() + msg['content-type'] = 'text/plain' + msg['content-transfer-encoding'] = '8bit' + msg.set_payload(x) + self.assertEqual(msg.get_payload(decode=True), + bytes(x, 'raw-unicode-escape')) + def test_questionable_bytes_payload(self): # This test improves coverage but is not a compliance test, - # since it involves poking inside the black box in a way - # that actually breaks the model invariants. + # since it involves poking inside the black box. x = 'this is a qu?stionable thing to do'.encode('utf-8') msg = Message() msg['content-type'] = 'text/plain; charset="utf-8"' -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 19:06:39 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 19:06:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2320531=3A_Apply_the_3=2E?= =?utf-8?q?3_version_of_the_=2319063_fix=2E?= Message-ID: <3fLPbM2HnYz7Lm9@mail.python.org> http://hg.python.org/cpython/rev/ef8aaace85ca changeset: 89019:ef8aaace85ca user: R David Murray date: Fri Feb 07 12:46:17 2014 -0500 summary: #20531: Apply the 3.3 version of the #19063 fix. So passing unicode to set_payload works again (but still doesn't do what you want when the message is serialized). files: Lib/email/charset.py | 11 ++---- Lib/email/message.py | 26 +++++++++++++-- Lib/test/test_email/test_email.py | 32 +++++++++++++++++++ Misc/NEWS | 4 ++ 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/Lib/email/charset.py b/Lib/email/charset.py --- a/Lib/email/charset.py +++ b/Lib/email/charset.py @@ -386,7 +386,8 @@ string using the ascii codec produces the correct string version of the content. """ - # 7bit/8bit encodings return the string unchanged (module conversions) + if not string: + return string if self.body_encoding is BASE64: if isinstance(string, str): string = string.encode(self.output_charset) @@ -398,13 +399,9 @@ # character set, then, we must turn it into pseudo bytes via the # latin1 charset, which will encode any byte as a single code point # between 0 and 255, which is what body_encode is expecting. - # - # Note that this clause doesn't handle the case of a _payload that - # is already bytes. It never did, and the semantics of _payload - # being bytes has never been nailed down, so fixing that is a - # longer term TODO. if isinstance(string, str): - string = string.encode(self.output_charset).decode('latin1') + string = string.encode(self.output_charset) + string = string.decode('latin1') return email.quoprimime.body_encode(string) else: if isinstance(string, str): diff --git a/Lib/email/message.py b/Lib/email/message.py --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -301,9 +301,19 @@ Optional charset sets the message's default character set. See set_charset() for details. """ - if isinstance(payload, bytes): - payload = payload.decode('ascii', 'surrogateescape') - self._payload = payload + if hasattr(payload, 'encode'): + if charset is None: + # We should check for ASCII-only here, but we can't do that + # for backward compatibility reasons. Fixed in 3.4. + self._payload = payload + return + if not isinstance(charset, Charset): + charset = Charset(charset) + payload = payload.encode(charset.output_charset) + if hasattr(payload, 'decode'): + self._payload = payload.decode('ascii', 'surrogateescape') + else: + self._payload = payload if charset is not None: self.set_charset(charset) @@ -342,7 +352,15 @@ try: cte(self) except TypeError: - self._payload = charset.body_encode(self._payload) + # This if is for backward compatibility and will be removed + # in 3.4 when the ascii check is added to set_payload. + payload = self._payload + if payload: + try: + payload = payload.encode('ascii', 'surrogateescape') + except UnicodeError: + payload = payload.encode(charset.output_charset) + self._payload = charset.body_encode(payload) self.add_header('Content-Transfer-Encoding', cte) def get_charset(self): diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -92,6 +92,38 @@ msg.set_payload('This is a string payload', charset) self.assertEqual(msg.get_charset().input_charset, 'iso-8859-1') + def test_set_payload_with_8bit_data_and_charset(self): + data = b'\xd0\x90\xd0\x91\xd0\x92' + charset = Charset('utf-8') + msg = Message() + msg.set_payload(data, charset) + self.assertEqual(msg['content-transfer-encoding'], 'base64') + self.assertEqual(msg.get_payload(decode=True), data) + self.assertEqual(msg.get_payload(), '0JDQkdCS\n') + + def test_set_payload_with_non_ascii_and_charset_body_encoding_none(self): + data = b'\xd0\x90\xd0\x91\xd0\x92' + charset = Charset('utf-8') + charset.body_encoding = None # Disable base64 encoding + msg = Message() + msg.set_payload(data.decode('utf-8'), charset) + self.assertEqual(msg['content-transfer-encoding'], '8bit') + self.assertEqual(msg.get_payload(decode=True), data) + + def test_set_payload_with_8bit_data_and_charset_body_encoding_none(self): + data = b'\xd0\x90\xd0\x91\xd0\x92' + charset = Charset('utf-8') + charset.body_encoding = None # Disable base64 encoding + msg = Message() + msg.set_payload(data, charset) + self.assertEqual(msg['content-transfer-encoding'], '8bit') + self.assertEqual(msg.get_payload(decode=True), data) + + def test_set_payload_to_list(self): + msg = Message() + msg.set_payload([]) + self.assertEqual(msg.get_payload(), []) + def test_get_charsets(self): eq = self.assertEqual diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,10 @@ Library ------- +- Issue #20531: Revert 3.4 version of fix for #19063, and apply the 3.3 + version. That is, do *not* raise an error if unicode is passed to + email.message.Message.set_payload. + - Issue #20476: If a non-compat32 policy is used with any of the email parsers, EmailMessage is now used as the factory class. The factory class should really come from the policy; that will get fixed in 3.5. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 19:06:40 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 19:06:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2319063=3A_the_unicode-in-set=5Fpayload_proble?= =?utf-8?q?m_isn=27t_getting_fixed_in_3=2E4=2E?= Message-ID: <3fLPbN3nkjz7LmK@mail.python.org> http://hg.python.org/cpython/rev/aab7258a31d3 changeset: 89020:aab7258a31d3 parent: 89019:ef8aaace85ca parent: 89017:4daf3cec9419 user: R David Murray date: Fri Feb 07 13:04:18 2014 -0500 summary: Merge: #19063: the unicode-in-set_payload problem isn't getting fixed in 3.4. files: Lib/email/message.py | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Lib/email/message.py b/Lib/email/message.py --- a/Lib/email/message.py +++ b/Lib/email/message.py @@ -303,8 +303,6 @@ """ if hasattr(payload, 'encode'): if charset is None: - # We should check for ASCII-only here, but we can't do that - # for backward compatibility reasons. Fixed in 3.4. self._payload = payload return if not isinstance(charset, Charset): @@ -352,8 +350,9 @@ try: cte(self) except TypeError: - # This if is for backward compatibility and will be removed - # in 3.4 when the ascii check is added to set_payload. + # This 'if' is for backward compatibility, it allows unicode + # through even though that won't work correctly if the + # message is serialized. payload = self._payload if payload: try: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 19:45:45 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 19:45:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2320013=3A_don=27t_raise_?= =?utf-8?q?socket_error_when_selected_mailbox_deleted=2E?= Message-ID: <3fLQST0Lc3z7Ljv@mail.python.org> http://hg.python.org/cpython/rev/a24f7d195b8f changeset: 89021:a24f7d195b8f user: R David Murray date: Fri Feb 07 13:44:57 2014 -0500 summary: #20013: don't raise socket error when selected mailbox deleted. I'm checking this in without a test because not much of this code is tested and I don't have time to work up the necessary extensions to the existing test framework. The patch itself was tested by the person who reported the bug. files: Lib/imaplib.py | 5 +++++ Misc/NEWS | 4 ++++ 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -1063,6 +1063,11 @@ del self.tagged_commands[tag] return result + # If we've seen a BYE at this point, the socket will be + # closed, so report the BYE now. + + self._check_bye() + # Some have reported "unexpected response" exceptions. # Note that ignoring them here causes loops. # Instead, send me details of the unexpected response and diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,10 @@ Library ------- +- Issue #20013: Some imap servers disconnect if the current mailbox is + deleted, and imaplib did not handle that case gracefully. Now it + handles the 'bye' correctly. + - Issue #20531: Revert 3.4 version of fix for #19063, and apply the 3.3 version. That is, do *not* raise an error if unicode is passed to email.message.Message.set_payload. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 19:51:55 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 19:51:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzIwMDEzOiBkb24n?= =?utf-8?q?t_raise_socket_error_when_selected_mailbox_deleted=2E?= Message-ID: <3fLQbb2HJcz7LjN@mail.python.org> http://hg.python.org/cpython/rev/aecc0a4be052 changeset: 89022:aecc0a4be052 branch: 3.3 parent: 89017:4daf3cec9419 user: R David Murray date: Fri Feb 07 13:47:40 2014 -0500 summary: #20013: don't raise socket error when selected mailbox deleted. I'm checking this in without a test because not much of this code is tested and I don't have time to work up the necessary extensions to the existing test framework. The patch itself was tested by the person who reported the bug. files: Lib/imaplib.py | 5 +++++ Misc/NEWS | 4 ++++ 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -1063,6 +1063,11 @@ del self.tagged_commands[tag] return result + # If we've seen a BYE at this point, the socket will be + # closed, so report the BYE now. + + self._check_bye() + # Some have reported "unexpected response" exceptions. # Note that ignoring them here causes loops. # Instead, send me details of the unexpected response and diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,10 @@ Library ------- +- Issue #20013: Some imap servers disconnect if the current mailbox is + deleted, and imaplib did not handle that case gracefully. Now it + handles the 'bye' correctly. + - Issue #19920: TarFile.list() no longer fails when outputs a listing containing non-encodable characters. Based on patch by Vajrasky Kok. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 19:51:56 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 19:51:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Null_merge_of_commit_accidentally_made_to_default_branch?= =?utf-8?q?_first=2E?= Message-ID: <3fLQbc3sqzz7LkV@mail.python.org> http://hg.python.org/cpython/rev/2e59d3dbf737 changeset: 89023:2e59d3dbf737 parent: 89021:a24f7d195b8f parent: 89022:aecc0a4be052 user: R David Murray date: Fri Feb 07 13:48:46 2014 -0500 summary: Null merge of commit accidentally made to default branch first. files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 19:51:57 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 19:51:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzIwMDEzOiBkb24n?= =?utf-8?q?t_raise_socket_error_when_selected_mailbox_deleted=2E?= Message-ID: <3fLQbd5n2sz7Llc@mail.python.org> http://hg.python.org/cpython/rev/16af3de2240f changeset: 89024:16af3de2240f branch: 2.7 parent: 89007:75c75d90f3a4 user: R David Murray date: Fri Feb 07 13:51:22 2014 -0500 summary: #20013: don't raise socket error when selected mailbox deleted. I'm checking this in without a test because not much of this code is tested and I don't have time to work up the necessary extensions to the existing test framework. The patch itself was tested by the person who reported the bug. files: Lib/imaplib.py | 5 +++++ Misc/NEWS | 4 ++++ 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Lib/imaplib.py b/Lib/imaplib.py --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -1002,6 +1002,11 @@ del self.tagged_commands[tag] return result + # If we've seen a BYE at this point, the socket will be + # closed, so report the BYE now. + + self._check_bye() + # Some have reported "unexpected response" exceptions. # Note that ignoring them here causes loops. # Instead, send me details of the unexpected response and diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,10 @@ Library ------- +- Issue #20013: Some imap servers disconnect if the current mailbox is + deleted, and imaplib did not handle that case gracefully. Now it + handles the 'bye' correctly. + - Issue #20426: When passing the re.DEBUG flag, re.compile() displays the debug output every time it is called, regardless of the compilation cache. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 21:05:03 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 21:05:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE3MzY5OiBJbXBy?= =?utf-8?q?ove_handling_of_broken_RFC2231_values_in_get=5Ffilename=2E?= Message-ID: <3fLSCz0wtwz7Ljv@mail.python.org> http://hg.python.org/cpython/rev/63f8ea0eeb6d changeset: 89025:63f8ea0eeb6d branch: 3.3 parent: 89022:aecc0a4be052 user: R David Murray date: Fri Feb 07 15:02:19 2014 -0500 summary: #17369: Improve handling of broken RFC2231 values in get_filename. This fixes a regression relative to python2. files: Lib/email/utils.py | 4 +++ Lib/test/test_email/test_email.py | 20 +++++++++++++++++++ Misc/NEWS | 4 +++ 3 files changed, 28 insertions(+), 0 deletions(-) diff --git a/Lib/email/utils.py b/Lib/email/utils.py --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -337,6 +337,10 @@ # object. We do not want bytes() normal utf-8 decoder, we want a straight # interpretation of the string as character bytes. charset, language, text = value + if charset is None: + # Issue 17369: if charset/lang is None, decode_rfc2231 couldn't parse + # the value, so use the fallback_charset. + charset = fallback_charset rawbytes = bytes(text, 'raw-unicode-escape') try: return str(rawbytes, charset, errors) diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -5018,6 +5018,26 @@ self.assertNotIsInstance(param, tuple) self.assertEqual(param, "Frank's Document") + def test_rfc2231_missing_tick(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="'This%20is%20broken"; +''' + msg = email.message_from_string(m) + self.assertEqual( + msg.get_filename(), + "'This is broken") + + def test_rfc2231_missing_tick_with_encoded_non_ascii(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="'This%20is%E2broken"; +''' + msg = email.message_from_string(m) + self.assertEqual( + msg.get_filename(), + "'This is\ufffdbroken") + # test_headerregistry.TestContentTypeHeader.rfc2231_single_quote_in_value_with_charset_and_lang def test_rfc2231_tick_attack_extended(self): eq = self.assertEqual diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -45,6 +45,10 @@ Library ------- +- Issue #17369: get_filename was raising an exception if the filename + parameter's RFC2231 encoding was broken in certain ways. This was + a regression relative to python2. + - Issue #20013: Some imap servers disconnect if the current mailbox is deleted, and imaplib did not handle that case gracefully. Now it handles the 'bye' correctly. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 21:05:04 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 7 Feb 2014 21:05:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2317369=3A_Improve_handling_of_broken_RFC2231_?= =?utf-8?q?values_in_get=5Ffilename=2E?= Message-ID: <3fLSD02qnWz7LmD@mail.python.org> http://hg.python.org/cpython/rev/e0a90b1c4cdf changeset: 89026:e0a90b1c4cdf parent: 89023:2e59d3dbf737 parent: 89025:63f8ea0eeb6d user: R David Murray date: Fri Feb 07 15:04:26 2014 -0500 summary: Merge: #17369: Improve handling of broken RFC2231 values in get_filename. files: Lib/email/utils.py | 4 +++ Lib/test/test_email/test_email.py | 20 +++++++++++++++++++ Misc/NEWS | 4 +++ 3 files changed, 28 insertions(+), 0 deletions(-) diff --git a/Lib/email/utils.py b/Lib/email/utils.py --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -347,6 +347,10 @@ # object. We do not want bytes() normal utf-8 decoder, we want a straight # interpretation of the string as character bytes. charset, language, text = value + if charset is None: + # Issue 17369: if charset/lang is None, decode_rfc2231 couldn't parse + # the value, so use the fallback_charset. + charset = fallback_charset rawbytes = bytes(text, 'raw-unicode-escape') try: return str(rawbytes, charset, errors) diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -5052,6 +5052,26 @@ self.assertNotIsInstance(param, tuple) self.assertEqual(param, "Frank's Document") + def test_rfc2231_missing_tick(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="'This%20is%20broken"; +''' + msg = email.message_from_string(m) + self.assertEqual( + msg.get_filename(), + "'This is broken") + + def test_rfc2231_missing_tick_with_encoded_non_ascii(self): + m = '''\ +Content-Disposition: inline; +\tfilename*0*="'This%20is%E2broken"; +''' + msg = email.message_from_string(m) + self.assertEqual( + msg.get_filename(), + "'This is\ufffdbroken") + # test_headerregistry.TestContentTypeHeader.rfc2231_single_quote_in_value_with_charset_and_lang def test_rfc2231_tick_attack_extended(self): eq = self.assertEqual diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,10 @@ Library ------- +- Issue #17369: get_filename was raising an exception if the filename + parameter's RFC2231 encoding was broken in certain ways. This was + a regression relative to python2. + - Issue #20013: Some imap servers disconnect if the current mailbox is deleted, and imaplib did not handle that case gracefully. Now it handles the 'bye' correctly. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 7 23:37:01 2014 From: python-checkins at python.org (victor.stinner) Date: Fri, 7 Feb 2014 23:37:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320505=3A_Remove_r?= =?utf-8?q?esolution_and_=5Fgranularity_from_selectors_and_asyncio?= Message-ID: <3fLWbK35C3z7LkV@mail.python.org> http://hg.python.org/cpython/rev/d853955491a2 changeset: 89027:d853955491a2 user: Victor Stinner date: Fri Feb 07 23:34:58 2014 +0100 summary: Issue #20505: Remove resolution and _granularity from selectors and asyncio * Remove selectors.BaseSelector.resolution attribute * Remove asyncio.BaseEventLoop._granularity attribute files: Doc/library/asyncio-eventloop.rst | 13 ------ Doc/library/selectors.rst | 4 - Lib/asyncio/base_events.py | 13 +----- Lib/asyncio/proactor_events.py | 1 - Lib/asyncio/selector_events.py | 1 - Lib/selectors.py | 21 ---------- Lib/test/test_asyncio/test_base_events.py | 3 +- Lib/test/test_asyncio/test_events.py | 23 +++------- Lib/test/test_selectors.py | 5 -- 9 files changed, 10 insertions(+), 74 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -118,19 +118,6 @@ implementation; ideally it is a monotonic clock. This will generally be a different clock than :func:`time.time`. -The granularity of the event loop depends on the resolution of the -:meth:`~BaseEventLoop.time` method and the resolution of the selector. It is -usually between 1 ms and 16 ms. For example, a granularity of 1 ms means that -in the best case, the difference between the expected delay and the real -elapsed time is between -1 ms and +1 ms: a call scheduled in 1 nanosecond may -be called in 1 ms, and a call scheduled in 100 ms may be called in 99 ms. - -The granularity is the best difference in theory. In practice, it depends on -the system load and the the time taken by tasks executed by the event loop. -For example, if a task blocks the event loop for 1 second, all tasks scheduled -in this second will be delayed. The :ref:`Handle correctly blocking functions -` section explains how to avoid such issue. - .. method:: BaseEventLoop.call_later(delay, callback, *args) diff --git a/Doc/library/selectors.rst b/Doc/library/selectors.rst --- a/Doc/library/selectors.rst +++ b/Doc/library/selectors.rst @@ -98,10 +98,6 @@ :class:`BaseSelector` and its concrete implementations support the :term:`context manager` protocol. - .. attribute:: resolution - - Resolution of the selector in seconds. - .. method:: register(fileobj, events, data=None) Register a file object for selection, monitoring it for I/O events. diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -96,7 +96,6 @@ self._default_executor = None self._internal_fds = 0 self._running = False - self._granularity = time.get_clock_info('monotonic').resolution def _make_socket_transport(self, sock, protocol, waiter=None, *, extra=None, server=None): @@ -634,21 +633,11 @@ else: logger.log(level, 'poll took %.3f seconds', t1-t0) else: - t0 = self.time() event_list = self._selector.select(timeout) - dt = self.time() - t0 - if timeout and not event_list and dt < timeout: - print("%s.select(%.3f ms) took %.3f ms (granularity=%.3f ms, resolution=%.3f ms)" - % (self._selector.__class__.__name__, - timeout * 1e3, - dt * 1e3, - self._granularity * 1e3, - self._selector.resolution * 1e3), - file=sys.__stderr__) self._process_events(event_list) # Handle 'later' callbacks that are ready. - now = self.time() + self._granularity + now = self.time() while self._scheduled: handle = self._scheduled[0] if handle._when > now: diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -365,7 +365,6 @@ self._selector = proactor # convenient alias self._self_reading_future = None self._accept_futures = {} # socket file descriptor => Future - self._granularity = max(proactor.resolution, self._granularity) proactor.set_loop(self) self._make_self_pipe() diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -36,7 +36,6 @@ selector = selectors.DefaultSelector() logger.debug('Using selector: %s', selector.__class__.__name__) self._selector = selector - self._granularity = max(selector.resolution, self._granularity) self._make_self_pipe() def _make_socket_transport(self, sock, protocol, waiter=None, *, diff --git a/Lib/selectors.py b/Lib/selectors.py --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -83,11 +83,6 @@ performant implementation on the current platform. """ - @abstractproperty - def resolution(self): - """Resolution of the selector in seconds""" - return None - @abstractmethod def register(self, fileobj, events, data=None): """Register a file object. @@ -289,10 +284,6 @@ self._readers = set() self._writers = set() - @property - def resolution(self): - return 1e-6 - def register(self, fileobj, events, data=None): key = super().register(fileobj, events, data) if events & EVENT_READ: @@ -345,10 +336,6 @@ super().__init__() self._poll = select.poll() - @property - def resolution(self): - return 1e-3 - def register(self, fileobj, events, data=None): key = super().register(fileobj, events, data) poll_events = 0 @@ -400,10 +387,6 @@ super().__init__() self._epoll = select.epoll() - @property - def resolution(self): - return 1e-3 - def fileno(self): return self._epoll.fileno() @@ -468,10 +451,6 @@ super().__init__() self._kqueue = select.kqueue() - @property - def resolution(self): - return 1e-9 - def fileno(self): return self._kqueue.fileno() diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -124,7 +124,8 @@ self.loop.run_forever() dt = self.loop.time() - t0 - self.assertGreaterEqual(dt, delay - self.loop._granularity, dt) + # 50 ms: maximum granularity of the event loop + self.assertGreaterEqual(dt, delay - 0.050, dt) # tolerate a difference of +800 ms because some Python buildbots # are really slow self.assertLessEqual(dt, 0.9, dt) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1170,28 +1170,19 @@ orig_run_once = self.loop._run_once self.loop._run_once_counter = 0 self.loop._run_once = _run_once - calls = [] @asyncio.coroutine def wait(): loop = self.loop - calls.append(loop._run_once_counter) - yield from asyncio.sleep(loop._granularity * 10, loop=loop) - calls.append(loop._run_once_counter) - yield from asyncio.sleep(loop._granularity / 10, loop=loop) - calls.append(loop._run_once_counter) + yield from asyncio.sleep(1e-2, loop=loop) + yield from asyncio.sleep(1e-4, loop=loop) self.loop.run_until_complete(wait()) - calls.append(self.loop._run_once_counter) - self.assertEqual(calls, [1, 3, 5, 6]) - - def test_granularity(self): - granularity = self.loop._granularity - self.assertGreater(granularity, 0.0) - # Worst expected granularity: 1 ms on Linux (limited by poll/epoll - # resolution), 15.6 ms on Windows (limited by time.monotonic - # resolution) - self.assertLess(granularity, 0.050) + # The ideal number of call is 6, but on some platforms, the selector + # may sleep at little bit less than timeout depending on the resolution + # of the clock used by the kernel. Tolerate 2 useless calls on these + # platforms. + self.assertLessEqual(self.loop._run_once_counter, 8) class SubprocessTestsMixin: diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -363,11 +363,6 @@ self.assertFalse(s.select(2)) self.assertLess(time() - t, 2.5) - def test_resolution(self): - s = self.SELECTOR() - self.assertIsInstance(s.resolution, (int, float)) - self.assertGreater(s.resolution, 0.0) - class ScalableSelectorMixIn: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 01:11:25 2014 From: python-checkins at python.org (guido.van.rossum) Date: Sat, 8 Feb 2014 01:11:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_More_asyncio_news=2E?= Message-ID: <3fLYhF11ftz7LjY@mail.python.org> http://hg.python.org/cpython/rev/b541ecd32115 changeset: 89028:b541ecd32115 user: Guido van Rossum date: Fri Feb 07 16:11:17 2014 -0800 summary: More asyncio news. files: Misc/NEWS | 16 +++++++++++----- 1 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -77,12 +77,18 @@ select.epoll.poll(), selectors.PollSelector.poll() and selectors.EpollSelector.poll(). For example, a timeout of one microsecond (1e-6) is now rounded to one millisecondi (1e-3), instead of being rounded to - zero. - -- asyncio: Some refactoring; add write flow control to unix pipes; - support wait_for(f, None); don't log broken/disconnected pipes; use + zero. However, the granularity property and asyncio's resolution feature + were removed again. + +- asyncio: Some refactoring; various fixes; add write flow control to + unix pipes; Future.set_exception() instantiates the exception + argument if it is a class; improved proactor pipe transport; support + wait_for(f, None); don't log broken/disconnected pipes; use ValueError instead of assert for forbidden subprocess_{shell,exec} - arguments. (More to follow -- a convenience API for subprocesses.) + arguments; added a convenience API for subprocess management; added + StreamReader.at_eof(); properly handle duplicate coroutines/futures + in gather(), wait(), as_completed(); use a bytearray for buffering + in StreamReader; and more. - Issue #20288: fix handling of invalid numeric charrefs in HTMLParser. -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sat Feb 8 09:52:57 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 08 Feb 2014 09:52:57 +0100 Subject: [Python-checkins] Daily reference leaks (b541ecd32115): sum=4 Message-ID: results for b541ecd32115 on branch "default" -------------------------------------------- test_site leaked [0, 0, 2] references, sum=2 test_site leaked [0, 0, 2] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogRqbXLp', '-x'] From python-checkins at python.org Sat Feb 8 10:44:49 2014 From: python-checkins at python.org (nick.coghlan) Date: Sat, 8 Feb 2014 10:44:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320478=3A_avoid_sp?= =?utf-8?q?ecial_casing_Counter_in_statistics?= Message-ID: <3fLpPs1k0gz7Ljn@mail.python.org> http://hg.python.org/cpython/rev/78d0b7472697 changeset: 89029:78d0b7472697 user: Nick Coghlan date: Sat Feb 08 19:44:16 2014 +1000 summary: Issue #20478: avoid special casing Counter in statistics Passing Counter objects to the Counter constructor is special cased, going through iter() firsts ensures they are handled the same way as any other iterable. (Committing on Steven's behalf as I don't believe his SSH key is registered yet) files: Lib/statistics.py | 4 +--- Lib/test/test_statistics.py | 8 ++++++++ Misc/NEWS | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Lib/statistics.py b/Lib/statistics.py --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -268,9 +268,7 @@ def _counts(data): # Generate a table of sorted (value, frequency) pairs. - if data is None: - raise TypeError('None is not iterable') - table = collections.Counter(data).most_common() + table = collections.Counter(iter(data)).most_common() if not table: return table # Extract the values with the highest frequency. diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -1355,6 +1355,14 @@ # collections.Counter, which accepts None and returns an empty dict. self.assertRaises(TypeError, self.func, None) + def test_counter_data(self): + # Test that a Counter is treated like any other iterable. + data = collections.Counter([1, 1, 1, 2]) + # Since the keys of the counter are treated as data points, not the + # counts, this should raise. + self.assertRaises(statistics.StatisticsError, self.func, data) + + # === Tests for variances and standard deviations === diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,9 @@ Library ------- +- Issue #20478: the statistics module now treats collections.Counter inputs + like any other iterable. + - Issue #17369: get_filename was raising an exception if the filename parameter's RFC2231 encoding was broken in certain ways. This was a regression relative to python2. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 10:48:00 2014 From: python-checkins at python.org (terry.reedy) Date: Sat, 8 Feb 2014 10:48:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320167=3A_Suppress?= =?utf-8?q?_3=2E4_specific_=27Exception_ignored=27_messages=2E?= Message-ID: <3fLpTX6dVWz7Ljm@mail.python.org> http://hg.python.org/cpython/rev/f9f2c57f7d00 changeset: 89030:f9f2c57f7d00 user: Terry Jan Reedy date: Sat Feb 08 04:47:29 2014 -0500 summary: Issue #20167: Suppress 3.4 specific 'Exception ignored' messages. Original patch by Tal Einat. files: Lib/idlelib/MultiCall.py | 27 +++++++++++++++++++++++---- 1 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Lib/idlelib/MultiCall.py b/Lib/idlelib/MultiCall.py --- a/Lib/idlelib/MultiCall.py +++ b/Lib/idlelib/MultiCall.py @@ -57,6 +57,13 @@ for number in range(len(_modifiers)) for name in _modifiers[number]]) +# In 3.4, if no shell window is ever open, the underlying Tk widget is +# destroyed before .__del__ methods here are called. The following +# is used to selectively ignore shutdown exceptions to avoid +# 'Exception ignored' messages. See http://bugs.python.org/issue20167 +APPLICATION_GONE = '''\ +can't invoke "bind" command: application has been destroyed''' + # A binder is a class which binds functions to one type of event. It has two # methods: bind and unbind, which get a function and a parsed sequence, as # returned by _parse_sequence(). There are two types of binders: @@ -98,7 +105,12 @@ def __del__(self): if self.handlerid: - self.widget.unbind(self.widgetinst, self.sequence, self.handlerid) + try: + self.widget.unbind(self.widgetinst, self.sequence, + self.handlerid) + except tkinter.TclError as e: + if e.args[0] == APPLICATION_GONE: + pass # An int in range(1 << len(_modifiers)) represents a combination of modifiers # (if the least significent bit is on, _modifiers[0] is on, and so on). @@ -227,7 +239,11 @@ def __del__(self): for seq, id in self.handlerids: - self.widget.unbind(self.widgetinst, seq, id) + try: + self.widget.unbind(self.widgetinst, seq, id) + except tkinter.TclError as e: + if e.args[0] == APPLICATION_GONE: + break # define the list of event types to be handled by MultiEvent. the order is # compatible with the definition of event type constants. @@ -390,8 +406,11 @@ func, triplets = self.__eventinfo[virtual] if func: for triplet in triplets: - self.__binders[triplet[1]].unbind(triplet, func) - + try: + self.__binders[triplet[1]].unbind(triplet, func) + except tkinter.TclError as e: + if e.args[0] == APPLICATION_GONE: + break _multicall_dict[widget] = MultiCall return MultiCall -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 11:14:09 2014 From: python-checkins at python.org (nick.coghlan) Date: Sat, 8 Feb 2014 11:14:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320481=3A_Disallow?= =?utf-8?q?_mixed_type_input_in_statistics?= Message-ID: <3fLq3j5gmhz7LjN@mail.python.org> http://hg.python.org/cpython/rev/5db74cd953ab changeset: 89031:5db74cd953ab user: Nick Coghlan date: Sat Feb 08 19:58:04 2014 +1000 summary: Close #20481: Disallow mixed type input in statistics The most appropriate coercion rules are not yet clear, so simply disallowing mixed type input for 3.4. (Committed on Steven's behalf) files: Doc/library/statistics.rst | 10 +++ Lib/statistics.py | 67 +++++++++--------------- Lib/test/test_statistics.py | 59 +++++++++------------ Misc/NEWS | 6 ++ 4 files changed, 66 insertions(+), 76 deletions(-) diff --git a/Doc/library/statistics.rst b/Doc/library/statistics.rst --- a/Doc/library/statistics.rst +++ b/Doc/library/statistics.rst @@ -20,6 +20,16 @@ This module provides functions for calculating mathematical statistics of numeric (:class:`Real`-valued) data. +.. note:: + + Unless explicitly noted otherwise, these functions support :class:`int`, + :class:`float`, :class:`decimal.Decimal` and :class:`fractions.Fraction`. + Behaviour with other types (whether in the numeric tower or not) is + currently unsupported. Mixed types are also undefined and + implementation-dependent. If your input data consists of mixed types, + you may be able to use :func:`map` to ensure a consistent result, e.g. + ``map(float, input_data)``. + Averages and measures of central location ----------------------------------------- diff --git a/Lib/statistics.py b/Lib/statistics.py --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -144,19 +144,31 @@ >>> _sum(data) Decimal('0.6963') + Mixed types are currently treated as an error, except that int is + allowed. """ + # We fail as soon as we reach a value that is not an int or the type of + # the first value which is not an int. E.g. _sum([int, int, float, int]) + # is okay, but sum([int, int, float, Fraction]) is not. + allowed_types = set([int, type(start)]) n, d = _exact_ratio(start) - T = type(start) partials = {d: n} # map {denominator: sum of numerators} # Micro-optimizations. - coerce_types = _coerce_types exact_ratio = _exact_ratio partials_get = partials.get - # Add numerators for each denominator, and track the "current" type. + # Add numerators for each denominator. for x in data: - T = _coerce_types(T, type(x)) + _check_type(type(x), allowed_types) n, d = exact_ratio(x) partials[d] = partials_get(d, 0) + n + # Find the expected result type. If allowed_types has only one item, it + # will be int; if it has two, use the one which isn't int. + assert len(allowed_types) in (1, 2) + if len(allowed_types) == 1: + assert allowed_types.pop() is int + T = int + else: + T = (allowed_types - set([int])).pop() if None in partials: assert issubclass(T, (float, Decimal)) assert not math.isfinite(partials[None]) @@ -172,6 +184,15 @@ return T(total) +def _check_type(T, allowed): + if T not in allowed: + if len(allowed) == 1: + allowed.add(T) + else: + types = ', '.join([t.__name__ for t in allowed] + [T.__name__]) + raise TypeError("unsupported mixed types: %s" % types) + + def _exact_ratio(x): """Convert Real number x exactly to (numerator, denominator) pair. @@ -228,44 +249,6 @@ return (num, den) -def _coerce_types(T1, T2): - """Coerce types T1 and T2 to a common type. - - >>> _coerce_types(int, float) - - - Coercion is performed according to this table, where "N/A" means - that a TypeError exception is raised. - - +----------+-----------+-----------+-----------+----------+ - | | int | Fraction | Decimal | float | - +----------+-----------+-----------+-----------+----------+ - | int | int | Fraction | Decimal | float | - | Fraction | Fraction | Fraction | N/A | float | - | Decimal | Decimal | N/A | Decimal | float | - | float | float | float | float | float | - +----------+-----------+-----------+-----------+----------+ - - Subclasses trump their parent class; two subclasses of the same - base class will be coerced to the second of the two. - - """ - # Get the common/fast cases out of the way first. - if T1 is T2: return T1 - if T1 is int: return T2 - if T2 is int: return T1 - # Subclasses trump their parent class. - if issubclass(T2, T1): return T2 - if issubclass(T1, T2): return T1 - # Floats trump everything else. - if issubclass(T2, float): return T2 - if issubclass(T1, float): return T1 - # Subclasses of the same base class give priority to the second. - if T1.__base__ is T2.__base__: return T2 - # Otherwise, just give up. - raise TypeError('cannot coerce types %r and %r' % (T1, T2)) - - def _counts(data): # Generate a table of sorted (value, frequency) pairs. table = collections.Counter(iter(data)).most_common() diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -687,6 +687,26 @@ self.assertRaises(ValueError, statistics._decimal_to_ratio, d) +class CheckTypeTest(unittest.TestCase): + # Test _check_type private function. + + def test_allowed(self): + # Test that a type which should be allowed is allowed. + allowed = set([int, float]) + statistics._check_type(int, allowed) + statistics._check_type(float, allowed) + + def test_not_allowed(self): + # Test that a type which should not be allowed raises. + allowed = set([int, float]) + self.assertRaises(TypeError, statistics._check_type, Decimal, allowed) + + def test_add_to_allowed(self): + # Test that a second type will be added to the allowed set. + allowed = set([int]) + statistics._check_type(float, allowed) + self.assertEqual(allowed, set([int, float])) + # === Tests for public functions === @@ -881,40 +901,11 @@ self.assertRaises(TypeError, self.func, [1, 2, 3, b'999']) def test_mixed_sum(self): - # Mixed sums are allowed. - - # Careful here: order matters. Can't mix Fraction and Decimal directly, - # only after they're converted to float. - data = [1, 2, Fraction(1, 2), 3.0, Decimal("0.25")] - self.assertEqual(self.func(data), 6.75) - - -class SumInternalsTest(NumericTestCase): - # Test internals of the sum function. - - def test_ignore_instance_float_method(self): - # Test that __float__ methods on data instances are ignored. - - # Python typically calls __dunder__ methods on the class, not the - # instance. The ``sum`` implementation calls __float__ directly. To - # better match the behaviour of Python, we call it only on the class, - # not the instance. This test will fail if somebody "fixes" that code. - - # Create a fake __float__ method. - def __float__(self): - raise AssertionError('test fails') - - # Inject it into an instance. - class MyNumber(Fraction): - pass - x = MyNumber(3) - x.__float__ = types.MethodType(__float__, x) - - # Check it works as expected. - self.assertRaises(AssertionError, x.__float__) - self.assertEqual(float(x), 3.0) - # And now test the function. - self.assertEqual(statistics._sum([1.0, 2.0, x, 4.0]), 10.0) + # Mixed input types are not (currently) allowed. + # Check that mixed data types fail. + self.assertRaises(TypeError, self.func, [1, 2.0, Fraction(1, 2)]) + # And so does mixed start argument. + self.assertRaises(TypeError, self.func, [1, 2.0], Decimal(1)) class SumTortureTest(NumericTestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,12 @@ Library ------- +- Issue #20481: For at least Python 3.4, the statistics module will require + that all inputs for a single operation be of a single consistent type, or + else a mixed of ints and a single other consistent type. This avoids + some interoperability issues that arose with the previous approach of + coercing to a suitable common type. + - Issue #20478: the statistics module now treats collections.Counter inputs like any other iterable. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 13:09:12 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 13:09:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTM4?= =?utf-8?q?=3A_UTF-7_incremental_decoder_produced_inconsistant_string_when?= Message-ID: <3fLscS0ftxz7Ljn@mail.python.org> http://hg.python.org/cpython/rev/8d40d9cee409 changeset: 89032:8d40d9cee409 branch: 3.3 parent: 89025:63f8ea0eeb6d user: Serhiy Storchaka date: Sat Feb 08 14:01:29 2014 +0200 summary: Issue #20538: UTF-7 incremental decoder produced inconsistant string when input was truncated in BASE64 section. files: Lib/test/test_codecs.py | 39 ++++++++++++++++++++++++---- Misc/NEWS | 3 ++ Objects/unicodeobject.c | 10 ++++++- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -852,13 +852,40 @@ def test_partial(self): self.check_partial( - "a+-b", + 'a+-b\x00c\x80d\u0100e\U00010000f', [ - "a", - "a", - "a+", - "a+-", - "a+-b", + 'a', + 'a', + 'a+', + 'a+-', + 'a+-b', + 'a+-b', + 'a+-b', + 'a+-b', + 'a+-b', + 'a+-b\x00', + 'a+-b\x00c', + 'a+-b\x00c', + 'a+-b\x00c', + 'a+-b\x00c', + 'a+-b\x00c', + 'a+-b\x00c\x80', + 'a+-b\x00c\x80d', + 'a+-b\x00c\x80d', + 'a+-b\x00c\x80d', + 'a+-b\x00c\x80d', + 'a+-b\x00c\x80d', + 'a+-b\x00c\x80d\u0100', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e\U00010000', + 'a+-b\x00c\x80d\u0100e\U00010000f', ] ) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #20538: UTF-7 incremental decoder produced inconsistant string when + input was truncated in BASE64 section. + - Issue #17825: Cursor "^" is correctly positioned for SyntaxError and IndentationError. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -4474,8 +4474,16 @@ /* return state */ if (consumed) { if (inShift) { + *consumed = startinpos; + if (outpos != shiftOutStart && + PyUnicode_MAX_CHAR_VALUE(unicode) > 127) { + PyObject *result = PyUnicode_FromKindAndData( + PyUnicode_KIND(unicode), PyUnicode_DATA(unicode), + shiftOutStart); + Py_DECREF(unicode); + unicode = result; + } outpos = shiftOutStart; /* back off output */ - *consumed = startinpos; } else { *consumed = s-starts; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 13:09:13 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 13:09:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320538=3A_UTF-7_incremental_decoder_produced_inc?= =?utf-8?q?onsistant_string_when?= Message-ID: <3fLscT2R4hz7LmZ@mail.python.org> http://hg.python.org/cpython/rev/e988661e458c changeset: 89033:e988661e458c parent: 89031:5db74cd953ab parent: 89032:8d40d9cee409 user: Serhiy Storchaka date: Sat Feb 08 14:06:33 2014 +0200 summary: Issue #20538: UTF-7 incremental decoder produced inconsistant string when input was truncated in BASE64 section. files: Lib/test/test_codecs.py | 41 +++++++++++++++++++++++----- Misc/NEWS | 3 ++ Objects/unicodeobject.c | 10 ++++++- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -124,8 +124,6 @@ "".join(codecs.iterdecode([bytes([c]) for c in encoded], self.encoding)) ) - # Temporary skip, see http://bugs.python.org/issue20542 - @unittest.skip def test_readline(self): def getreader(input): stream = io.BytesIO(input.encode(self.encoding)) @@ -899,13 +897,40 @@ def test_partial(self): self.check_partial( - "a+-b", + 'a+-b\x00c\x80d\u0100e\U00010000f', [ - "a", - "a", - "a+", - "a+-", - "a+-b", + 'a', + 'a', + 'a+', + 'a+-', + 'a+-b', + 'a+-b', + 'a+-b', + 'a+-b', + 'a+-b', + 'a+-b\x00', + 'a+-b\x00c', + 'a+-b\x00c', + 'a+-b\x00c', + 'a+-b\x00c', + 'a+-b\x00c', + 'a+-b\x00c\x80', + 'a+-b\x00c\x80d', + 'a+-b\x00c\x80d', + 'a+-b\x00c\x80d', + 'a+-b\x00c\x80d', + 'a+-b\x00c\x80d', + 'a+-b\x00c\x80d\u0100', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e', + 'a+-b\x00c\x80d\u0100e\U00010000', + 'a+-b\x00c\x80d\u0100e\U00010000f', ] ) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #20538: UTF-7 incremental decoder produced inconsistant string when + input was truncated in BASE64 section. + - Issue #20404: io.TextIOWrapper (and hence the open() builtin) now uses the internal codec marking system added for issue #19619 to throw LookupError for known non-text encodings at stream construction time. The existing diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -4459,8 +4459,16 @@ /* return state */ if (consumed) { if (inShift) { + *consumed = startinpos; + if (writer.pos != shiftOutStart && writer.maxchar > 127) { + PyObject *result = PyUnicode_FromKindAndData( + writer.kind, writer.data, shiftOutStart); + Py_XDECREF(errorHandler); + Py_XDECREF(exc); + _PyUnicodeWriter_Dealloc(&writer); + return result; + } writer.pos = shiftOutStart; /* back off output */ - *consumed = startinpos; } else { *consumed = s-starts; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:07:58 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 14:07:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTQ2?= =?utf-8?q?=3A_Use_specific_asserts_in_int_tests=2E?= Message-ID: <3fLtwG1hDTz7Ljn@mail.python.org> http://hg.python.org/cpython/rev/e47c46ede37e changeset: 89034:e47c46ede37e branch: 2.7 parent: 89024:16af3de2240f user: Serhiy Storchaka date: Sat Feb 08 14:28:20 2014 +0200 summary: Issue #20546: Use specific asserts in int tests. files: Lib/test/test_long.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -90,7 +90,7 @@ # The sign of the number is also random. def getran(self, ndigits): - self.assertTrue(ndigits > 0) + self.assertGreater(ndigits, 0) nbits_hi = ndigits * SHIFT nbits_lo = nbits_hi - SHIFT + 1 answer = 0L @@ -588,7 +588,7 @@ pass x = long2(1L<<100) y = int(x) - self.assertTrue(type(y) is long, + self.assertIs(type(y), long, "overflowing int conversion must return long not long subtype") # long -> Py_ssize_t conversion -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:07:59 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 14:07:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTQ2?= =?utf-8?q?=3A_Use_specific_asserts_in_int_tests=2E?= Message-ID: <3fLtwH44Zlz7LmZ@mail.python.org> http://hg.python.org/cpython/rev/265446b8b48c changeset: 89035:265446b8b48c branch: 3.3 parent: 89032:8d40d9cee409 user: Serhiy Storchaka date: Sat Feb 08 14:28:33 2014 +0200 summary: Issue #20546: Use specific asserts in int tests. files: Lib/test/test_long.py | 48 +++++++++++++++--------------- 1 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -130,7 +130,7 @@ # The sign of the number is also random. def getran(self, ndigits): - self.assertTrue(ndigits > 0) + self.assertGreater(ndigits, 0) nbits_hi = ndigits * SHIFT nbits_lo = nbits_hi - SHIFT + 1 answer = 0 @@ -865,21 +865,21 @@ def test_small_ints(self): for i in range(-5, 257): - self.assertTrue(i is i + 0) - self.assertTrue(i is i * 1) - self.assertTrue(i is i - 0) - self.assertTrue(i is i // 1) - self.assertTrue(i is i & -1) - self.assertTrue(i is i | 0) - self.assertTrue(i is i ^ 0) - self.assertTrue(i is ~~i) - self.assertTrue(i is i**1) - self.assertTrue(i is int(str(i))) - self.assertTrue(i is i<<2>>2, str(i)) + self.assertIs(i, i + 0) + self.assertIs(i, i * 1) + self.assertIs(i, i - 0) + self.assertIs(i, i // 1) + self.assertIs(i, i & -1) + self.assertIs(i, i | 0) + self.assertIs(i, i ^ 0) + self.assertIs(i, ~~i) + self.assertIs(i, i**1) + self.assertIs(i, int(str(i))) + self.assertIs(i, i<<2>>2, str(i)) # corner cases i = 1 << 70 - self.assertTrue(i - i is 0) - self.assertTrue(0 * i is 0) + self.assertIs(i - i, 0) + self.assertIs(0 * i, 0) def test_bit_length(self): tiny = 1e-10 @@ -926,7 +926,7 @@ got = round(k+offset, -1) expected = v+offset self.assertEqual(got, expected) - self.assertTrue(type(got) is int) + self.assertIs(type(got), int) # larger second argument self.assertEqual(round(-150, -2), -200) @@ -965,7 +965,7 @@ got = round(10**k + 324678, -3) expect = 10**k + 325000 self.assertEqual(got, expect) - self.assertTrue(type(got) is int) + self.assertIs(type(got), int) # nonnegative second argument: round(x, n) should just return x for n in range(5): @@ -973,7 +973,7 @@ x = random.randrange(-10000, 10000) got = round(x, n) self.assertEqual(got, x) - self.assertTrue(type(got) is int) + self.assertIs(type(got), int) for huge_n in 2**31-1, 2**31, 2**63-1, 2**63, 2**100, 10**100: self.assertEqual(round(8979323, huge_n), 8979323) @@ -982,7 +982,7 @@ x = random.randrange(-10000, 10000) got = round(x) self.assertEqual(got, x) - self.assertTrue(type(got) is int) + self.assertIs(type(got), int) # bad second argument bad_exponents = ('brian', 2.0, 0j, None) @@ -1187,15 +1187,15 @@ class myint(int): pass - self.assertTrue(type(myint.from_bytes(b'\x00', 'big')) is myint) + self.assertIs(type(myint.from_bytes(b'\x00', 'big')), myint) self.assertEqual(myint.from_bytes(b'\x01', 'big'), 1) - self.assertTrue( - type(myint.from_bytes(b'\x00', 'big', signed=False)) is myint) + self.assertIs( + type(myint.from_bytes(b'\x00', 'big', signed=False)), myint) self.assertEqual(myint.from_bytes(b'\x01', 'big', signed=False), 1) - self.assertTrue(type(myint.from_bytes(b'\x00', 'little')) is myint) + self.assertIs(type(myint.from_bytes(b'\x00', 'little')), myint) self.assertEqual(myint.from_bytes(b'\x01', 'little'), 1) - self.assertTrue(type(myint.from_bytes( - b'\x00', 'little', signed=False)) is myint) + self.assertIs(type(myint.from_bytes( + b'\x00', 'little', signed=False)), myint) self.assertEqual(myint.from_bytes(b'\x01', 'little', signed=False), 1) self.assertEqual( int.from_bytes([255, 0, 0], 'big', signed=True), -65536) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:08:00 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 14:08:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320546=3A_Use_specific_asserts_in_int_tests=2E?= Message-ID: <3fLtwJ6SmKz7LnD@mail.python.org> http://hg.python.org/cpython/rev/79ddfbea25d7 changeset: 89036:79ddfbea25d7 parent: 89033:e988661e458c parent: 89035:265446b8b48c user: Serhiy Storchaka date: Sat Feb 08 14:29:36 2014 +0200 summary: Issue #20546: Use specific asserts in int tests. files: Lib/test/test_long.py | 48 +++++++++++++++--------------- 1 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -130,7 +130,7 @@ # The sign of the number is also random. def getran(self, ndigits): - self.assertTrue(ndigits > 0) + self.assertGreater(ndigits, 0) nbits_hi = ndigits * SHIFT nbits_lo = nbits_hi - SHIFT + 1 answer = 0 @@ -865,21 +865,21 @@ def test_small_ints(self): for i in range(-5, 257): - self.assertTrue(i is i + 0) - self.assertTrue(i is i * 1) - self.assertTrue(i is i - 0) - self.assertTrue(i is i // 1) - self.assertTrue(i is i & -1) - self.assertTrue(i is i | 0) - self.assertTrue(i is i ^ 0) - self.assertTrue(i is ~~i) - self.assertTrue(i is i**1) - self.assertTrue(i is int(str(i))) - self.assertTrue(i is i<<2>>2, str(i)) + self.assertIs(i, i + 0) + self.assertIs(i, i * 1) + self.assertIs(i, i - 0) + self.assertIs(i, i // 1) + self.assertIs(i, i & -1) + self.assertIs(i, i | 0) + self.assertIs(i, i ^ 0) + self.assertIs(i, ~~i) + self.assertIs(i, i**1) + self.assertIs(i, int(str(i))) + self.assertIs(i, i<<2>>2, str(i)) # corner cases i = 1 << 70 - self.assertTrue(i - i is 0) - self.assertTrue(0 * i is 0) + self.assertIs(i - i, 0) + self.assertIs(0 * i, 0) def test_bit_length(self): tiny = 1e-10 @@ -926,7 +926,7 @@ got = round(k+offset, -1) expected = v+offset self.assertEqual(got, expected) - self.assertTrue(type(got) is int) + self.assertIs(type(got), int) # larger second argument self.assertEqual(round(-150, -2), -200) @@ -965,7 +965,7 @@ got = round(10**k + 324678, -3) expect = 10**k + 325000 self.assertEqual(got, expect) - self.assertTrue(type(got) is int) + self.assertIs(type(got), int) # nonnegative second argument: round(x, n) should just return x for n in range(5): @@ -973,7 +973,7 @@ x = random.randrange(-10000, 10000) got = round(x, n) self.assertEqual(got, x) - self.assertTrue(type(got) is int) + self.assertIs(type(got), int) for huge_n in 2**31-1, 2**31, 2**63-1, 2**63, 2**100, 10**100: self.assertEqual(round(8979323, huge_n), 8979323) @@ -982,7 +982,7 @@ x = random.randrange(-10000, 10000) got = round(x) self.assertEqual(got, x) - self.assertTrue(type(got) is int) + self.assertIs(type(got), int) # bad second argument bad_exponents = ('brian', 2.0, 0j, None) @@ -1187,15 +1187,15 @@ class myint(int): pass - self.assertTrue(type(myint.from_bytes(b'\x00', 'big')) is myint) + self.assertIs(type(myint.from_bytes(b'\x00', 'big')), myint) self.assertEqual(myint.from_bytes(b'\x01', 'big'), 1) - self.assertTrue( - type(myint.from_bytes(b'\x00', 'big', signed=False)) is myint) + self.assertIs( + type(myint.from_bytes(b'\x00', 'big', signed=False)), myint) self.assertEqual(myint.from_bytes(b'\x01', 'big', signed=False), 1) - self.assertTrue(type(myint.from_bytes(b'\x00', 'little')) is myint) + self.assertIs(type(myint.from_bytes(b'\x00', 'little')), myint) self.assertEqual(myint.from_bytes(b'\x01', 'little'), 1) - self.assertTrue(type(myint.from_bytes( - b'\x00', 'little', signed=False)) is myint) + self.assertIs(type(myint.from_bytes( + b'\x00', 'little', signed=False)), myint) self.assertEqual(myint.from_bytes(b'\x01', 'little', signed=False), 1) self.assertEqual( int.from_bytes([255, 0, 0], 'big', signed=True), -65536) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:08:02 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 14:08:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTU1?= =?utf-8?q?=3A_Use_specific_asserts_in_urllib=2C_httplib=2C_ftplib=2C_cgi?= =?utf-8?q?=2C_wsgiref?= Message-ID: <3fLtwL1vRKz7LnY@mail.python.org> http://hg.python.org/cpython/rev/b21397ca58c7 changeset: 89037:b21397ca58c7 branch: 2.7 parent: 89034:e47c46ede37e user: Serhiy Storchaka date: Sat Feb 08 14:49:55 2014 +0200 summary: Issue #20555: Use specific asserts in urllib, httplib, ftplib, cgi, wsgiref tests. files: Lib/test/test_cgi.py | 2 +- Lib/test/test_ftplib.py | 6 ++-- Lib/test/test_httplib.py | 6 ++-- Lib/test/test_httpservers.py | 2 +- Lib/test/test_urllib.py | 4 +- Lib/test/test_urllib2.py | 7 +++-- Lib/test/test_urllib2net.py | 26 ++++++++++++------------ Lib/test/test_wsgiref.py | 4 +- 8 files changed, 29 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -232,7 +232,7 @@ # if we're not chunking properly, readline is only called twice # (by read_binary); if we are chunking properly, it will be called 5 times # as long as the chunksize is 1 << 16. - self.assertTrue(f.numcalls > 2) + self.assertGreater(f.numcalls, 2) def test_fieldstorage_invalid(self): fs = cgi.FieldStorage() diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -740,7 +740,7 @@ def testTimeoutDefault(self): # default -- use global socket timeout - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: ftp = ftplib.FTP(HOST) @@ -752,13 +752,13 @@ def testTimeoutNone(self): # no timeout -- do not use global socket timeout - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: ftp = ftplib.FTP(HOST, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(ftp.sock.gettimeout() is None) + self.assertIsNone(ftp.sock.gettimeout()) self.evt.wait() ftp.close() diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -123,7 +123,7 @@ conn.sock = FakeSocket(None) conn.putrequest('GET','/') conn.putheader('Content-length',42) - self.assertTrue('Content-length: 42' in conn._buffer) + self.assertIn('Content-length: 42', conn._buffer) def test_ipv6host_header(self): # Default host header on IPv6 transaction should wrapped by [] if @@ -466,7 +466,7 @@ HTTPConnection and into the socket. ''' # default -- use global socket timeout - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT) @@ -477,7 +477,7 @@ httpConn.close() # no timeout -- do not use global socket default - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: httpConn = httplib.HTTPConnection(HOST, TimeoutTest.PORT, diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -114,7 +114,7 @@ def verify_http_server_response(self, response): match = self.HTTPResponseMatch.search(response) - self.assertTrue(match is not None) + self.assertIsNotNone(match) def test_http_1_1(self): result = self.send_typical_request('GET / HTTP/1.1\r\n\r\n') diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -878,7 +878,7 @@ # def testTimeoutNone(self): # # global default timeout is ignored # import socket -# self.assertTrue(socket.getdefaulttimeout() is None) +# self.assertIsNone(socket.getdefaulttimeout()) # socket.setdefaulttimeout(30) # try: # ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, []) @@ -890,7 +890,7 @@ # def testTimeoutDefault(self): # # global default timeout is used # import socket -# self.assertTrue(socket.getdefaulttimeout() is None) +# self.assertIsNone(socket.getdefaulttimeout()) # socket.setdefaulttimeout(30) # try: # ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, []) diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -591,8 +591,8 @@ self.assertIsInstance(args[0], Request) # response from opener.open is None, because there's no # handler that defines http_open to handle it - self.assertTrue(args[1] is None or - isinstance(args[1], MockResponse)) + if args[1] is not None: + self.assertIsInstance(args[1], MockResponse) def sanepathname2url(path): @@ -924,7 +924,8 @@ MockHeaders({"location": to_url})) except urllib2.HTTPError: # 307 in response to POST requires user OK - self.assertTrue(code == 307 and data is not None) + self.assertEqual(code, 307) + self.assertIsNotNone(data) self.assertEqual(o.req.get_full_url(), to_url) try: self.assertEqual(o.req.get_method(), "GET") diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -80,11 +80,11 @@ # delve deep into response to fetch socket._socketobject response = _urlopen_with_retry("http://www.python.org/") abused_fileobject = response.fp - self.assertTrue(abused_fileobject.__class__ is socket._fileobject) + self.assertIs(abused_fileobject.__class__, socket._fileobject) httpresponse = abused_fileobject._sock - self.assertTrue(httpresponse.__class__ is httplib.HTTPResponse) + self.assertIs(httpresponse.__class__, httplib.HTTPResponse) fileobject = httpresponse.fp - self.assertTrue(fileobject.__class__ is socket._fileobject) + self.assertIs(fileobject.__class__, socket._fileobject) self.assertTrue(not fileobject.closed) response.close() @@ -250,14 +250,14 @@ class TimeoutTest(unittest.TestCase): def test_http_basic(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) url = "http://www.python.org" with test_support.transient_internet(url, timeout=None): u = _urlopen_with_retry(url) - self.assertTrue(u.fp._sock.fp._sock.gettimeout() is None) + self.assertIsNone(u.fp._sock.fp._sock.gettimeout()) def test_http_default_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) url = "http://www.python.org" with test_support.transient_internet(url): socket.setdefaulttimeout(60) @@ -268,7 +268,7 @@ self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 60) def test_http_no_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) url = "http://www.python.org" with test_support.transient_internet(url): socket.setdefaulttimeout(60) @@ -276,7 +276,7 @@ u = _urlopen_with_retry(url, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(u.fp._sock.fp._sock.gettimeout() is None) + self.assertIsNone(u.fp._sock.fp._sock.gettimeout()) def test_http_timeout(self): url = "http://www.python.org" @@ -287,13 +287,13 @@ FTP_HOST = "ftp://ftp.mirror.nl/pub/gnu/" def test_ftp_basic(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) with test_support.transient_internet(self.FTP_HOST, timeout=None): u = _urlopen_with_retry(self.FTP_HOST) - self.assertTrue(u.fp.fp._sock.gettimeout() is None) + self.assertIsNone(u.fp.fp._sock.gettimeout()) def test_ftp_default_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) with test_support.transient_internet(self.FTP_HOST): socket.setdefaulttimeout(60) try: @@ -303,14 +303,14 @@ self.assertEqual(u.fp.fp._sock.gettimeout(), 60) def test_ftp_no_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout(),) with test_support.transient_internet(self.FTP_HOST): socket.setdefaulttimeout(60) try: u = _urlopen_with_retry(self.FTP_HOST, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(u.fp.fp._sock.gettimeout() is None) + self.assertIsNone(u.fp.fp._sock.gettimeout()) def test_ftp_timeout(self): with test_support.transient_internet(self.FTP_HOST): diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py --- a/Lib/test/test_wsgiref.py +++ b/Lib/test/test_wsgiref.py @@ -155,7 +155,7 @@ # Check existing value env = {key:alt} util.setup_testing_defaults(env) - self.assertTrue(env[key] is alt) + self.assertIs(env[key], alt) def checkCrossDefault(self,key,value,**kw): util.setup_testing_defaults(kw) @@ -302,7 +302,7 @@ self.assertEqual(Headers(test[:]).keys(), ['x']) self.assertEqual(Headers(test[:]).values(), ['y']) self.assertEqual(Headers(test[:]).items(), test) - self.assertFalse(Headers(test).items() is test) # must be copy! + self.assertIsNot(Headers(test).items(), test) # must be copy! h=Headers([]) del h['foo'] # should not raise an error -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:08:03 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 14:08:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTU1?= =?utf-8?q?=3A_Use_specific_asserts_in_urllib=2C_httplib=2C_ftplib=2C_cgi?= =?utf-8?q?=2C_wsgiref?= Message-ID: <3fLtwM4xWHz7LmZ@mail.python.org> http://hg.python.org/cpython/rev/b6f8d5148a05 changeset: 89038:b6f8d5148a05 branch: 3.3 parent: 89035:265446b8b48c user: Serhiy Storchaka date: Sat Feb 08 14:50:08 2014 +0200 summary: Issue #20555: Use specific asserts in urllib, httplib, ftplib, cgi, wsgiref tests. files: Lib/test/test_cgi.py | 2 +- Lib/test/test_ftplib.py | 6 +++--- Lib/test/test_httplib.py | 6 +++--- Lib/test/test_httpservers.py | 2 +- Lib/test/test_urllib.py | 4 ++-- Lib/test/test_urllib2.py | 7 ++++--- Lib/test/test_urllib2net.py | 22 +++++++++++----------- Lib/test/test_wsgiref.py | 4 ++-- 8 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -227,7 +227,7 @@ # if we're not chunking properly, readline is only called twice # (by read_binary); if we are chunking properly, it will be called 5 times # as long as the chunksize is 1 << 16. - self.assertTrue(f.numcalls > 2) + self.assertGreater(f.numcalls, 2) f.close() def test_fieldstorage_multipart(self): diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -965,7 +965,7 @@ def testTimeoutDefault(self): # default -- use global socket timeout - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: ftp = ftplib.FTP(HOST) @@ -977,13 +977,13 @@ def testTimeoutNone(self): # no timeout -- do not use global socket timeout - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: ftp = ftplib.FTP(HOST, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(ftp.sock.gettimeout() is None) + self.assertIsNone(ftp.sock.gettimeout()) self.evt.wait() ftp.close() diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -132,7 +132,7 @@ conn.sock = FakeSocket(None) conn.putrequest('GET','/') conn.putheader('Content-length', 42) - self.assertTrue(b'Content-length: 42' in conn._buffer) + self.assertIn(b'Content-length: 42', conn._buffer) def test_ipv6host_header(self): # Default host header on IPv6 transaction should wrapped by [] if @@ -699,7 +699,7 @@ # and into the socket. # default -- use global socket timeout - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: httpConn = client.HTTPConnection(HOST, TimeoutTest.PORT) @@ -710,7 +710,7 @@ httpConn.close() # no timeout -- do not use global socket default - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: httpConn = client.HTTPConnection(HOST, TimeoutTest.PORT, diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -531,7 +531,7 @@ def verify_http_server_response(self, response): match = self.HTTPResponseMatch.search(response) - self.assertTrue(match is not None) + self.assertIsNotNone(match) def test_http_1_1(self): result = self.send_typical_request(b'GET / HTTP/1.1\r\n\r\n') diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -1264,7 +1264,7 @@ # def testTimeoutNone(self): # # global default timeout is ignored # import socket -# self.assertTrue(socket.getdefaulttimeout() is None) +# self.assertIsNone(socket.getdefaulttimeout()) # socket.setdefaulttimeout(30) # try: # ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, []) @@ -1276,7 +1276,7 @@ # def testTimeoutDefault(self): # # global default timeout is used # import socket -# self.assertTrue(socket.getdefaulttimeout() is None) +# self.assertIsNone(socket.getdefaulttimeout()) # socket.setdefaulttimeout(30) # try: # ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, []) diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -594,8 +594,8 @@ self.assertIsInstance(args[0], Request) # response from opener.open is None, because there's no # handler that defines http_open to handle it - self.assertTrue(args[1] is None or - isinstance(args[1], MockResponse)) + if args[1] is not None: + self.assertIsInstance(args[1], MockResponse) def test_method_deprecations(self): req = Request("http://www.example.com") @@ -1000,7 +1000,8 @@ MockHeaders({"location": to_url})) except urllib.error.HTTPError: # 307 in response to POST requires user OK - self.assertTrue(code == 307 and data is not None) + self.assertEqual(code, 307) + self.assertIsNotNone(data) self.assertEqual(o.req.get_full_url(), to_url) try: self.assertEqual(o.req.get_method(), "GET") diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -85,7 +85,7 @@ with support.transient_internet(url): response = _urlopen_with_retry(url) sock = response.fp - self.assertTrue(not sock.closed) + self.assertFalse(sock.closed) response.close() self.assertTrue(sock.closed) @@ -252,15 +252,15 @@ class TimeoutTest(unittest.TestCase): def test_http_basic(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) url = "http://www.python.org" with support.transient_internet(url, timeout=None): u = _urlopen_with_retry(url) self.addCleanup(u.close) - self.assertTrue(u.fp.raw._sock.gettimeout() is None) + self.assertIsNone(u.fp.raw._sock.gettimeout()) def test_http_default_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) url = "http://www.python.org" with support.transient_internet(url): socket.setdefaulttimeout(60) @@ -272,7 +272,7 @@ self.assertEqual(u.fp.raw._sock.gettimeout(), 60) def test_http_no_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) url = "http://www.python.org" with support.transient_internet(url): socket.setdefaulttimeout(60) @@ -281,7 +281,7 @@ self.addCleanup(u.close) finally: socket.setdefaulttimeout(None) - self.assertTrue(u.fp.raw._sock.gettimeout() is None) + self.assertIsNone(u.fp.raw._sock.gettimeout()) def test_http_timeout(self): url = "http://www.python.org" @@ -293,14 +293,14 @@ FTP_HOST = "ftp://ftp.mirror.nl/pub/gnu/" def test_ftp_basic(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) with support.transient_internet(self.FTP_HOST, timeout=None): u = _urlopen_with_retry(self.FTP_HOST) self.addCleanup(u.close) - self.assertTrue(u.fp.fp.raw._sock.gettimeout() is None) + self.assertIsNone(u.fp.fp.raw._sock.gettimeout()) def test_ftp_default_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) with support.transient_internet(self.FTP_HOST): socket.setdefaulttimeout(60) try: @@ -311,7 +311,7 @@ self.assertEqual(u.fp.fp.raw._sock.gettimeout(), 60) def test_ftp_no_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) with support.transient_internet(self.FTP_HOST): socket.setdefaulttimeout(60) try: @@ -319,7 +319,7 @@ self.addCleanup(u.close) finally: socket.setdefaulttimeout(None) - self.assertTrue(u.fp.fp.raw._sock.gettimeout() is None) + self.assertIsNone(u.fp.fp.raw._sock.gettimeout()) def test_ftp_timeout(self): with support.transient_internet(self.FTP_HOST): diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py --- a/Lib/test/test_wsgiref.py +++ b/Lib/test/test_wsgiref.py @@ -196,7 +196,7 @@ # Check existing value env = {key:alt} util.setup_testing_defaults(env) - self.assertTrue(env[key] is alt) + self.assertIs(env[key], alt) def checkCrossDefault(self,key,value,**kw): util.setup_testing_defaults(kw) @@ -343,7 +343,7 @@ self.assertEqual(Headers(test[:]).keys(), ['x']) self.assertEqual(Headers(test[:]).values(), ['y']) self.assertEqual(Headers(test[:]).items(), test) - self.assertFalse(Headers(test).items() is test) # must be copy! + self.assertIsNot(Headers(test).items(), test) # must be copy! h=Headers([]) del h['foo'] # should not raise an error -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:08:05 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 14:08:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320555=3A_Use_specific_asserts_in_urllib=2C_http?= =?utf-8?q?lib=2C_ftplib=2C_cgi=2C_wsgiref?= Message-ID: <3fLtwP14S7z7Lnf@mail.python.org> http://hg.python.org/cpython/rev/868675190b34 changeset: 89039:868675190b34 parent: 89036:79ddfbea25d7 parent: 89038:b6f8d5148a05 user: Serhiy Storchaka date: Sat Feb 08 14:51:10 2014 +0200 summary: Issue #20555: Use specific asserts in urllib, httplib, ftplib, cgi, wsgiref tests. files: Lib/test/test_cgi.py | 2 +- Lib/test/test_ftplib.py | 6 +++--- Lib/test/test_httplib.py | 6 +++--- Lib/test/test_httpservers.py | 2 +- Lib/test/test_urllib.py | 4 ++-- Lib/test/test_urllib2.py | 7 ++++--- Lib/test/test_urllib2net.py | 22 +++++++++++----------- Lib/test/test_wsgiref.py | 4 ++-- 8 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -227,7 +227,7 @@ # if we're not chunking properly, readline is only called twice # (by read_binary); if we are chunking properly, it will be called 5 times # as long as the chunksize is 1 << 16. - self.assertTrue(f.numcalls > 2) + self.assertGreater(f.numcalls, 2) f.close() def test_fieldstorage_multipart(self): diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -1001,7 +1001,7 @@ def testTimeoutDefault(self): # default -- use global socket timeout - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: ftp = ftplib.FTP(HOST) @@ -1013,13 +1013,13 @@ def testTimeoutNone(self): # no timeout -- do not use global socket timeout - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: ftp = ftplib.FTP(HOST, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(ftp.sock.gettimeout() is None) + self.assertIsNone(ftp.sock.gettimeout()) self.evt.wait() ftp.close() diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -134,7 +134,7 @@ conn.sock = FakeSocket(None) conn.putrequest('GET','/') conn.putheader('Content-length', 42) - self.assertTrue(b'Content-length: 42' in conn._buffer) + self.assertIn(b'Content-length: 42', conn._buffer) def test_ipv6host_header(self): # Default host header on IPv6 transaction should wrapped by [] if @@ -723,7 +723,7 @@ # and into the socket. # default -- use global socket timeout - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: httpConn = client.HTTPConnection(HOST, TimeoutTest.PORT) @@ -734,7 +734,7 @@ httpConn.close() # no timeout -- do not use global socket default - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: httpConn = client.HTTPConnection(HOST, TimeoutTest.PORT, diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -552,7 +552,7 @@ def verify_http_server_response(self, response): match = self.HTTPResponseMatch.search(response) - self.assertTrue(match is not None) + self.assertIsNotNone(match) def test_http_1_1(self): result = self.send_typical_request(b'GET / HTTP/1.1\r\n\r\n') diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -1340,7 +1340,7 @@ # def testTimeoutNone(self): # # global default timeout is ignored # import socket -# self.assertTrue(socket.getdefaulttimeout() is None) +# self.assertIsNone(socket.getdefaulttimeout()) # socket.setdefaulttimeout(30) # try: # ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, []) @@ -1352,7 +1352,7 @@ # def testTimeoutDefault(self): # # global default timeout is used # import socket -# self.assertTrue(socket.getdefaulttimeout() is None) +# self.assertIsNone(socket.getdefaulttimeout()) # socket.setdefaulttimeout(30) # try: # ftp = urllib.ftpwrapper("myuser", "mypass", "localhost", 9093, []) diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -603,8 +603,8 @@ self.assertIsInstance(args[0], Request) # response from opener.open is None, because there's no # handler that defines http_open to handle it - self.assertTrue(args[1] is None or - isinstance(args[1], MockResponse)) + if args[1] is not None: + self.assertIsInstance(args[1], MockResponse) def sanepathname2url(path): try: @@ -1018,7 +1018,8 @@ MockHeaders({"location": to_url})) except urllib.error.HTTPError: # 307 in response to POST requires user OK - self.assertTrue(code == 307 and data is not None) + self.assertEqual(code, 307) + self.assertIsNotNone(data) self.assertEqual(o.req.get_full_url(), to_url) try: self.assertEqual(o.req.get_method(), "GET") diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -87,7 +87,7 @@ with support.transient_internet(url): response = _urlopen_with_retry(url) sock = response.fp - self.assertTrue(not sock.closed) + self.assertFalse(sock.closed) response.close() self.assertTrue(sock.closed) @@ -262,15 +262,15 @@ class TimeoutTest(unittest.TestCase): def test_http_basic(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) url = "http://www.python.org" with support.transient_internet(url, timeout=None): u = _urlopen_with_retry(url) self.addCleanup(u.close) - self.assertTrue(u.fp.raw._sock.gettimeout() is None) + self.assertIsNone(u.fp.raw._sock.gettimeout()) def test_http_default_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) url = "http://www.python.org" with support.transient_internet(url): socket.setdefaulttimeout(60) @@ -282,7 +282,7 @@ self.assertEqual(u.fp.raw._sock.gettimeout(), 60) def test_http_no_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) url = "http://www.python.org" with support.transient_internet(url): socket.setdefaulttimeout(60) @@ -291,7 +291,7 @@ self.addCleanup(u.close) finally: socket.setdefaulttimeout(None) - self.assertTrue(u.fp.raw._sock.gettimeout() is None) + self.assertIsNone(u.fp.raw._sock.gettimeout()) def test_http_timeout(self): url = "http://www.python.org" @@ -303,14 +303,14 @@ FTP_HOST = "ftp://ftp.mirror.nl/pub/gnu/" def test_ftp_basic(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) with support.transient_internet(self.FTP_HOST, timeout=None): u = _urlopen_with_retry(self.FTP_HOST) self.addCleanup(u.close) - self.assertTrue(u.fp.fp.raw._sock.gettimeout() is None) + self.assertIsNone(u.fp.fp.raw._sock.gettimeout()) def test_ftp_default_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) with support.transient_internet(self.FTP_HOST): socket.setdefaulttimeout(60) try: @@ -321,7 +321,7 @@ self.assertEqual(u.fp.fp.raw._sock.gettimeout(), 60) def test_ftp_no_timeout(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) with support.transient_internet(self.FTP_HOST): socket.setdefaulttimeout(60) try: @@ -329,7 +329,7 @@ self.addCleanup(u.close) finally: socket.setdefaulttimeout(None) - self.assertTrue(u.fp.fp.raw._sock.gettimeout() is None) + self.assertIsNone(u.fp.fp.raw._sock.gettimeout()) def test_ftp_timeout(self): with support.transient_internet(self.FTP_HOST): diff --git a/Lib/test/test_wsgiref.py b/Lib/test/test_wsgiref.py --- a/Lib/test/test_wsgiref.py +++ b/Lib/test/test_wsgiref.py @@ -196,7 +196,7 @@ # Check existing value env = {key:alt} util.setup_testing_defaults(env) - self.assertTrue(env[key] is alt) + self.assertIs(env[key], alt) def checkCrossDefault(self,key,value,**kw): util.setup_testing_defaults(kw) @@ -343,7 +343,7 @@ self.assertEqual(Headers(test[:]).keys(), ['x']) self.assertEqual(Headers(test[:]).values(), ['y']) self.assertEqual(Headers(test[:]).items(), test) - self.assertFalse(Headers(test).items() is test) # must be copy! + self.assertIsNot(Headers(test).items(), test) # must be copy! h=Headers([]) del h['foo'] # should not raise an error -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:08:06 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 14:08:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTQ5?= =?utf-8?q?=3A_Use_specific_asserts_in_mailbox=2C_smtplib_and_poplib_tests?= =?utf-8?q?=2E?= Message-ID: <3fLtwQ46xnz7Lmq@mail.python.org> http://hg.python.org/cpython/rev/1c3fcba31708 changeset: 89040:1c3fcba31708 branch: 2.7 parent: 89037:b21397ca58c7 user: Serhiy Storchaka date: Sat Feb 08 15:05:53 2014 +0200 summary: Issue #20549: Use specific asserts in mailbox, smtplib and poplib tests. files: Lib/test/test_mailbox.py | 64 ++++++++++++++-------------- Lib/test/test_poplib.py | 6 +- Lib/test/test_smtplib.py | 6 +- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -138,7 +138,7 @@ msg = self._box.get(key0) self.assertEqual(msg['from'], 'foo') self.assertEqual(msg.get_payload(), '0\n') - self.assertIs(self._box.get('foo'), None) + self.assertIsNone(self._box.get('foo')) self.assertFalse(self._box.get('foo', False)) self._box.close() self._box = self._factory(self._path, factory=rfc822.Message) @@ -249,8 +249,7 @@ count = 0 for value in returned_values: self.assertEqual(value['from'], 'foo') - self.assertTrue(int(value.get_payload()) < repetitions, - (value.get_payload(), repetitions)) + self.assertLess(int(value.get_payload()), repetitions) count += 1 self.assertEqual(len(values), count) @@ -664,7 +663,7 @@ "tmp")), "File in wrong location: '%s'" % head) match = pattern.match(tail) - self.assertTrue(match is not None, "Invalid file name: '%s'" % tail) + self.assertIsNotNone(match, "Invalid file name: '%s'" % tail) groups = match.groups() if previous_groups is not None: self.assertGreaterEqual(int(groups[0]), int(previous_groups[0]), @@ -674,22 +673,22 @@ self.assertGreaterEqual(int(groups[1]), int(previous_groups[1]), "Non-monotonic milliseconds: '%s' before '%s'" % (previous_groups[1], groups[1])) - self.assertTrue(int(groups[2]) == pid, + self.assertEqual(int(groups[2]), pid, "Process ID mismatch: '%s' should be '%s'" % (groups[2], pid)) - self.assertTrue(int(groups[3]) == int(previous_groups[3]) + 1, + self.assertEqual(int(groups[3]), int(previous_groups[3]) + 1, "Non-sequential counter: '%s' before '%s'" % (previous_groups[3], groups[3])) - self.assertTrue(groups[4] == hostname, + self.assertEqual(groups[4], hostname, "Host name mismatch: '%s' should be '%s'" % (groups[4], hostname)) previous_groups = groups tmp_file.write(_sample_message) tmp_file.seek(0) - self.assertTrue(tmp_file.read() == _sample_message) + self.assertEqual(tmp_file.read(), _sample_message) tmp_file.close() file_count = len(os.listdir(os.path.join(self._path, "tmp"))) - self.assertTrue(file_count == repetitions, + self.assertEqual(file_count, repetitions, "Wrong file count: '%s' should be '%s'" % (file_count, repetitions)) @@ -1240,7 +1239,7 @@ self.assertIsInstance(msg, self._factory) self.assertEqual(msg.keys(), []) self.assertFalse(msg.is_multipart()) - self.assertEqual(msg.get_payload(), None) + self.assertIsNone(msg.get_payload()) def test_initialize_incorrectly(self): # Initialize with invalid argument @@ -1313,7 +1312,7 @@ # Use get_date() and set_date() msg = mailbox.MaildirMessage(_sample_message) diff = msg.get_date() - time.time() - self.assertTrue(abs(diff) < 60, diff) + self.assertLess(abs(diff), 60, diff) msg.set_date(0.0) self.assertEqual(msg.get_date(), 0.0) @@ -1388,8 +1387,9 @@ # Check contents of "From " line if sender is None: sender = "MAILER-DAEMON" - self.assertTrue(re.match(sender + r" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:" - r"\d{2} \d{4}", msg.get_from())) + self.assertIsNotNone(re.match( + sender + r" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:\d{2} \d{4}", + msg.get_from())) class TestMboxMessage(_TestMboxMMDFMessage, TestMessage): @@ -1463,7 +1463,7 @@ msg = mailbox.BabylMessage(_sample_message) visible = msg.get_visible() self.assertEqual(visible.keys(), []) - self.assertIs(visible.get_payload(), None) + self.assertIsNone(visible.get_payload()) visible['User-Agent'] = 'FooBar 1.0' visible['X-Whatever'] = 'Blah' self.assertEqual(msg.get_visible().keys(), []) @@ -1472,10 +1472,10 @@ self.assertEqual(visible.keys(), ['User-Agent', 'X-Whatever']) self.assertEqual(visible['User-Agent'], 'FooBar 1.0') self.assertEqual(visible['X-Whatever'], 'Blah') - self.assertIs(visible.get_payload(), None) + self.assertIsNone(visible.get_payload()) msg.update_visible() self.assertEqual(visible.keys(), ['User-Agent', 'X-Whatever']) - self.assertIs(visible.get_payload(), None) + self.assertIsNone(visible.get_payload()) visible = msg.get_visible() self.assertEqual(visible.keys(), ['User-Agent', 'Date', 'From', 'To', 'Subject']) @@ -1971,43 +1971,43 @@ # Make sure the boxes attribute actually gets set. self.mbox = mailbox.Maildir(test_support.TESTFN) #self.assertTrue(hasattr(self.mbox, "boxes")) - #self.assertTrue(len(self.mbox.boxes) == 0) - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + #self.assertEqual(len(self.mbox.boxes), 0) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) def test_nonempty_maildir_cur(self): self.createMessage("cur") self.mbox = mailbox.Maildir(test_support.TESTFN) - #self.assertTrue(len(self.mbox.boxes) == 1) + #self.assertEqual(len(self.mbox.boxes), 1) msg = self.mbox.next() - self.assertIsNot(msg, None) + self.assertIsNotNone(msg) msg.fp.close() - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) def test_nonempty_maildir_new(self): self.createMessage("new") self.mbox = mailbox.Maildir(test_support.TESTFN) - #self.assertTrue(len(self.mbox.boxes) == 1) + #self.assertEqual(len(self.mbox.boxes), 1) msg = self.mbox.next() - self.assertIsNot(msg, None) + self.assertIsNotNone(msg) msg.fp.close() - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) def test_nonempty_maildir_both(self): self.createMessage("cur") self.createMessage("new") self.mbox = mailbox.Maildir(test_support.TESTFN) - #self.assertTrue(len(self.mbox.boxes) == 2) + #self.assertEqual(len(self.mbox.boxes), 2) msg = self.mbox.next() - self.assertIsNot(msg, None) + self.assertIsNotNone(msg) msg.fp.close() msg = self.mbox.next() - self.assertIsNot(msg, None) + self.assertIsNotNone(msg) msg.fp.close() - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) def test_unix_mbox(self): ### should be better! diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -308,7 +308,7 @@ serv.close() def testTimeoutDefault(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: pop = poplib.POP3(HOST, self.port) @@ -318,13 +318,13 @@ pop.sock.close() def testTimeoutNone(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: pop = poplib.POP3(HOST, self.port, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(pop.sock.gettimeout() is None) + self.assertIsNone(pop.sock.gettimeout()) pop.sock.close() def testTimeoutValue(self): diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -77,7 +77,7 @@ smtp.close() def testTimeoutDefault(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: smtp = smtplib.SMTP(HOST, self.port) @@ -87,13 +87,13 @@ smtp.close() def testTimeoutNone(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: smtp = smtplib.SMTP(HOST, self.port, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(smtp.sock.gettimeout() is None) + self.assertIsNone(smtp.sock.gettimeout()) smtp.close() def testTimeoutValue(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:08:08 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 14:08:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTQ5?= =?utf-8?q?=3A_Use_specific_asserts_in_mailbox=2C_smtplib_and_poplib_tests?= =?utf-8?q?=2E?= Message-ID: <3fLtwS08sZz7Lmn@mail.python.org> http://hg.python.org/cpython/rev/bd1d6916b689 changeset: 89041:bd1d6916b689 branch: 3.3 parent: 89038:b6f8d5148a05 user: Serhiy Storchaka date: Sat Feb 08 15:06:08 2014 +0200 summary: Issue #20549: Use specific asserts in mailbox, smtplib and poplib tests. files: Lib/test/test_mailbox.py | 47 ++++++++++++++------------- Lib/test/test_poplib.py | 6 +- Lib/test/test_smtplib.py | 6 +- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -233,7 +233,7 @@ msg = self._box.get(key0) self.assertEqual(msg['from'], 'foo') self.assertEqual(msg.get_payload(), '0\n') - self.assertIs(self._box.get('foo'), None) + self.assertIsNone(self._box.get('foo')) self.assertIs(self._box.get('foo', False), False) self._box.close() self._box = self._factory(self._path) @@ -760,7 +760,7 @@ "tmp")), "File in wrong location: '%s'" % head) match = pattern.match(tail) - self.assertIsNot(match, None, "Invalid file name: '%s'" % tail) + self.assertIsNotNone(match, "Invalid file name: '%s'" % tail) groups = match.groups() if previous_groups is not None: self.assertGreaterEqual(int(groups[0]), int(previous_groups[0]), @@ -1394,7 +1394,7 @@ self.assertIsInstance(msg, self._factory) self.assertEqual(msg.keys(), []) self.assertFalse(msg.is_multipart()) - self.assertEqual(msg.get_payload(), None) + self.assertIsNone(msg.get_payload()) def test_initialize_incorrectly(self): # Initialize with invalid argument @@ -1405,7 +1405,7 @@ eMM = email.message_from_string(_sample_message) msg = self._factory(_sample_message) for attr in eMM.__dict__: - self.assertTrue(attr in msg.__dict__, + self.assertIn(attr, msg.__dict__, '{} attribute does not exist'.format(attr)) def test_become_message(self): @@ -1547,8 +1547,9 @@ # Check contents of "From " line if sender is None: sender = "MAILER-DAEMON" - self.assertTrue(re.match(sender + r" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:" - r"\d{2} \d{4}", msg.get_from()) is not None) + self.assertIsNotNone(re.match( + sender + r" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:\d{2} \d{4}", + msg.get_from())) class TestMboxMessage(_TestMboxMMDFMessage, TestMessage): @@ -1622,19 +1623,19 @@ msg = mailbox.BabylMessage(_sample_message) visible = msg.get_visible() self.assertEqual(visible.keys(), []) - self.assertIs(visible.get_payload(), None) + self.assertIsNone(visible.get_payload()) visible['User-Agent'] = 'FooBar 1.0' visible['X-Whatever'] = 'Blah' self.assertEqual(msg.get_visible().keys(), []) msg.set_visible(visible) visible = msg.get_visible() - self.assertTrue(visible.keys() == ['User-Agent', 'X-Whatever']) - self.assertTrue(visible['User-Agent'] == 'FooBar 1.0') + self.assertEqual(visible.keys(), ['User-Agent', 'X-Whatever']) + self.assertEqual(visible['User-Agent'], 'FooBar 1.0') self.assertEqual(visible['X-Whatever'], 'Blah') - self.assertIs(visible.get_payload(), None) + self.assertIsNone(visible.get_payload()) msg.update_visible() self.assertEqual(visible.keys(), ['User-Agent', 'X-Whatever']) - self.assertIs(visible.get_payload(), None) + self.assertIsNone(visible.get_payload()) visible = msg.get_visible() self.assertEqual(visible.keys(), ['User-Agent', 'Date', 'From', 'To', 'Subject']) @@ -2156,34 +2157,34 @@ self.mbox = mailbox.Maildir(support.TESTFN) #self.assertTrue(hasattr(self.mbox, "boxes")) #self.assertEqual(len(self.mbox.boxes), 0) - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) def test_nonempty_maildir_cur(self): self.createMessage("cur") self.mbox = mailbox.Maildir(support.TESTFN) #self.assertEqual(len(self.mbox.boxes), 1) - self.assertIsNot(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNotNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) def test_nonempty_maildir_new(self): self.createMessage("new") self.mbox = mailbox.Maildir(support.TESTFN) #self.assertEqual(len(self.mbox.boxes), 1) - self.assertIsNot(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNotNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) def test_nonempty_maildir_both(self): self.createMessage("cur") self.createMessage("new") self.mbox = mailbox.Maildir(support.TESTFN) #self.assertEqual(len(self.mbox.boxes), 2) - self.assertIsNot(self.mbox.next(), None) - self.assertIsNot(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNotNone(self.mbox.next()) + self.assertIsNotNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) ## End: tests from the original module (for backward compatibility). diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -350,7 +350,7 @@ serv.close() def testTimeoutDefault(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: pop = poplib.POP3(HOST, self.port) @@ -360,13 +360,13 @@ pop.sock.close() def testTimeoutNone(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: pop = poplib.POP3(HOST, self.port, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(pop.sock.gettimeout() is None) + self.assertIsNone(pop.sock.gettimeout()) pop.sock.close() def testTimeoutValue(self): diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -96,7 +96,7 @@ def testTimeoutDefault(self): mock_socket.reply_with(b"220 Hola mundo") - self.assertTrue(mock_socket.getdefaulttimeout() is None) + self.assertIsNone(mock_socket.getdefaulttimeout()) mock_socket.setdefaulttimeout(30) self.assertEqual(mock_socket.getdefaulttimeout(), 30) try: @@ -108,13 +108,13 @@ def testTimeoutNone(self): mock_socket.reply_with(b"220 Hola mundo") - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: smtp = smtplib.SMTP(HOST, self.port, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(smtp.sock.gettimeout() is None) + self.assertIsNone(smtp.sock.gettimeout()) smtp.close() def testTimeoutValue(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:08:09 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 14:08:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320549=3A_Use_specific_asserts_in_mailbox=2C_smt?= =?utf-8?q?plib_and_poplib_tests=2E?= Message-ID: <3fLtwT2hvbz7LmZ@mail.python.org> http://hg.python.org/cpython/rev/2e5e66f9e228 changeset: 89042:2e5e66f9e228 parent: 89039:868675190b34 parent: 89041:bd1d6916b689 user: Serhiy Storchaka date: Sat Feb 08 15:06:43 2014 +0200 summary: Issue #20549: Use specific asserts in mailbox, smtplib and poplib tests. files: Lib/test/test_mailbox.py | 47 ++++++++++++++------------- Lib/test/test_poplib.py | 6 +- Lib/test/test_smtplib.py | 6 +- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -233,7 +233,7 @@ msg = self._box.get(key0) self.assertEqual(msg['from'], 'foo') self.assertEqual(msg.get_payload(), '0\n') - self.assertIs(self._box.get('foo'), None) + self.assertIsNone(self._box.get('foo')) self.assertIs(self._box.get('foo', False), False) self._box.close() self._box = self._factory(self._path) @@ -760,7 +760,7 @@ "tmp")), "File in wrong location: '%s'" % head) match = pattern.match(tail) - self.assertIsNot(match, None, "Invalid file name: '%s'" % tail) + self.assertIsNotNone(match, "Invalid file name: '%s'" % tail) groups = match.groups() if previous_groups is not None: self.assertGreaterEqual(int(groups[0]), int(previous_groups[0]), @@ -1394,7 +1394,7 @@ self.assertIsInstance(msg, self._factory) self.assertEqual(msg.keys(), []) self.assertFalse(msg.is_multipart()) - self.assertEqual(msg.get_payload(), None) + self.assertIsNone(msg.get_payload()) def test_initialize_incorrectly(self): # Initialize with invalid argument @@ -1405,7 +1405,7 @@ eMM = email.message_from_string(_sample_message) msg = self._factory(_sample_message) for attr in eMM.__dict__: - self.assertTrue(attr in msg.__dict__, + self.assertIn(attr, msg.__dict__, '{} attribute does not exist'.format(attr)) def test_become_message(self): @@ -1547,8 +1547,9 @@ # Check contents of "From " line if sender is None: sender = "MAILER-DAEMON" - self.assertTrue(re.match(sender + r" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:" - r"\d{2} \d{4}", msg.get_from()) is not None) + self.assertIsNotNone(re.match( + sender + r" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:\d{2} \d{4}", + msg.get_from())) class TestMboxMessage(_TestMboxMMDFMessage, TestMessage): @@ -1622,19 +1623,19 @@ msg = mailbox.BabylMessage(_sample_message) visible = msg.get_visible() self.assertEqual(visible.keys(), []) - self.assertIs(visible.get_payload(), None) + self.assertIsNone(visible.get_payload()) visible['User-Agent'] = 'FooBar 1.0' visible['X-Whatever'] = 'Blah' self.assertEqual(msg.get_visible().keys(), []) msg.set_visible(visible) visible = msg.get_visible() - self.assertTrue(visible.keys() == ['User-Agent', 'X-Whatever']) - self.assertTrue(visible['User-Agent'] == 'FooBar 1.0') + self.assertEqual(visible.keys(), ['User-Agent', 'X-Whatever']) + self.assertEqual(visible['User-Agent'], 'FooBar 1.0') self.assertEqual(visible['X-Whatever'], 'Blah') - self.assertIs(visible.get_payload(), None) + self.assertIsNone(visible.get_payload()) msg.update_visible() self.assertEqual(visible.keys(), ['User-Agent', 'X-Whatever']) - self.assertIs(visible.get_payload(), None) + self.assertIsNone(visible.get_payload()) visible = msg.get_visible() self.assertEqual(visible.keys(), ['User-Agent', 'Date', 'From', 'To', 'Subject']) @@ -2156,34 +2157,34 @@ self.mbox = mailbox.Maildir(support.TESTFN) #self.assertTrue(hasattr(self.mbox, "boxes")) #self.assertEqual(len(self.mbox.boxes), 0) - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) def test_nonempty_maildir_cur(self): self.createMessage("cur") self.mbox = mailbox.Maildir(support.TESTFN) #self.assertEqual(len(self.mbox.boxes), 1) - self.assertIsNot(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNotNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) def test_nonempty_maildir_new(self): self.createMessage("new") self.mbox = mailbox.Maildir(support.TESTFN) #self.assertEqual(len(self.mbox.boxes), 1) - self.assertIsNot(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNotNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) def test_nonempty_maildir_both(self): self.createMessage("cur") self.createMessage("new") self.mbox = mailbox.Maildir(support.TESTFN) #self.assertEqual(len(self.mbox.boxes), 2) - self.assertIsNot(self.mbox.next(), None) - self.assertIsNot(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) - self.assertIs(self.mbox.next(), None) + self.assertIsNotNone(self.mbox.next()) + self.assertIsNotNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) + self.assertIsNone(self.mbox.next()) ## End: tests from the original module (for backward compatibility). diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -468,7 +468,7 @@ serv.close() def testTimeoutDefault(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: pop = poplib.POP3(HOST, self.port) @@ -478,13 +478,13 @@ pop.sock.close() def testTimeoutNone(self): - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: pop = poplib.POP3(HOST, self.port, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(pop.sock.gettimeout() is None) + self.assertIsNone(pop.sock.gettimeout()) pop.sock.close() def testTimeoutValue(self): diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -96,7 +96,7 @@ def testTimeoutDefault(self): mock_socket.reply_with(b"220 Hola mundo") - self.assertTrue(mock_socket.getdefaulttimeout() is None) + self.assertIsNone(mock_socket.getdefaulttimeout()) mock_socket.setdefaulttimeout(30) self.assertEqual(mock_socket.getdefaulttimeout(), 30) try: @@ -108,13 +108,13 @@ def testTimeoutNone(self): mock_socket.reply_with(b"220 Hola mundo") - self.assertTrue(socket.getdefaulttimeout() is None) + self.assertIsNone(socket.getdefaulttimeout()) socket.setdefaulttimeout(30) try: smtp = smtplib.SMTP(HOST, self.port, timeout=None) finally: socket.setdefaulttimeout(None) - self.assertTrue(smtp.sock.gettimeout() is None) + self.assertIsNone(smtp.sock.gettimeout()) smtp.close() def testTimeoutValue(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:21:14 2014 From: python-checkins at python.org (nick.coghlan) Date: Sat, 8 Feb 2014 14:21:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE4ODA1?= =?utf-8?q?=3A_better_netmask_validation_in_ipaddress?= Message-ID: <3fLvCZ0CThz7Lk9@mail.python.org> http://hg.python.org/cpython/rev/ca5ea7c24370 changeset: 89043:ca5ea7c24370 branch: 3.3 parent: 89041:bd1d6916b689 user: Nick Coghlan date: Sat Feb 08 23:17:36 2014 +1000 summary: Issue #18805: better netmask validation in ipaddress files: Lib/ipaddress.py | 148 ++++++++++++++---------- Lib/test/test_ipaddress.py | 73 ++++++++--- Misc/NEWS | 3 + 3 files changed, 139 insertions(+), 85 deletions(-) diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -456,8 +456,8 @@ raise AddressValueError(msg % (address, address_len, expected_len, self._version)) - def _ip_int_from_prefix(self, prefixlen=None): - """Turn the prefix length netmask into a int for comparison. + def _ip_int_from_prefix(self, prefixlen): + """Turn the prefix length into a bitwise netmask Args: prefixlen: An integer, the prefix length. @@ -466,36 +466,92 @@ An integer. """ - if prefixlen is None: - prefixlen = self._prefixlen return self._ALL_ONES ^ (self._ALL_ONES >> prefixlen) - def _prefix_from_ip_int(self, ip_int, mask=32): - """Return prefix length from the decimal netmask. + def _prefix_from_ip_int(self, ip_int): + """Return prefix length from the bitwise netmask. Args: - ip_int: An integer, the IP address. - mask: The netmask. Defaults to 32. + ip_int: An integer, the netmask in axpanded bitwise format Returns: An integer, the prefix length. + Raises: + ValueError: If the input intermingles zeroes & ones """ - return mask - _count_righthand_zero_bits(ip_int, mask) + trailing_zeroes = _count_righthand_zero_bits(ip_int, + self._max_prefixlen) + prefixlen = self._max_prefixlen - trailing_zeroes + leading_ones = ip_int >> trailing_zeroes + all_ones = (1 << prefixlen) - 1 + if leading_ones != all_ones: + byteslen = self._max_prefixlen // 8 + details = ip_int.to_bytes(byteslen, 'big') + msg = 'Netmask pattern %r mixes zeroes & ones' + raise ValueError(msg % details) + return prefixlen - def _ip_string_from_prefix(self, prefixlen=None): - """Turn a prefix length into a dotted decimal string. + def _report_invalid_netmask(self, netmask_str): + msg = '%r is not a valid netmask' % netmask_str + raise NetmaskValueError(msg) from None + + def _prefix_from_prefix_string(self, prefixlen_str): + """Return prefix length from a numeric string Args: - prefixlen: An integer, the netmask prefix length. + prefixlen_str: The string to be converted Returns: - A string, the dotted decimal netmask string. + An integer, the prefix length. + Raises: + NetmaskValueError: If the input is not a valid netmask """ - if not prefixlen: - prefixlen = self._prefixlen - return self._string_from_ip_int(self._ip_int_from_prefix(prefixlen)) + # int allows a leading +/- as well as surrounding whitespace, + # so we ensure that isn't the case + if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str): + self._report_invalid_netmask(prefixlen_str) + try: + prefixlen = int(prefixlen_str) + except ValueError: + self._report_invalid_netmask(prefixlen_str) + if not (0 <= prefixlen <= self._max_prefixlen): + self._report_invalid_netmask(prefixlen_str) + return prefixlen + + def _prefix_from_ip_string(self, ip_str): + """Turn a netmask/hostmask string into a prefix length + + Args: + ip_str: The netmask/hostmask to be converted + + Returns: + An integer, the prefix length. + + Raises: + NetmaskValueError: If the input is not a valid netmask/hostmask + """ + # Parse the netmask/hostmask like an IP address. + try: + ip_int = self._ip_int_from_string(ip_str) + except AddressValueError: + self._report_invalid_netmask(ip_str) + + # Try matching a netmask (this would be /1*0*/ as a bitwise regexp). + # Note that the two ambiguous cases (all-ones and all-zeroes) are + # treated as netmasks. + try: + return self._prefix_from_ip_int(ip_int) + except ValueError: + pass + + # Invert the bits, and try matching a /0+1+/ hostmask instead. + ip_int ^= self._ALL_ONES + try: + return self._prefix_from_ip_int(ip_int) + except ValueError: + self._report_invalid_netmask(ip_str) class _BaseAddress(_IPAddressBase): @@ -504,7 +560,6 @@ This IP class contains the version independent methods which are used by single IP addresses. - """ def __init__(self, address): @@ -873,7 +928,7 @@ raise ValueError('prefix length diff must be > 0') new_prefixlen = self._prefixlen + prefixlen_diff - if not self._is_valid_netmask(str(new_prefixlen)): + if new_prefixlen > self._max_prefixlen: raise ValueError( 'prefix length diff %d is invalid for netblock %s' % ( new_prefixlen, self)) @@ -1428,33 +1483,16 @@ self.network_address = IPv4Address(self._ip_int_from_string(addr[0])) if len(addr) == 2: - mask = addr[1].split('.') - - if len(mask) == 4: - # We have dotted decimal netmask. - if self._is_valid_netmask(addr[1]): - self.netmask = IPv4Address(self._ip_int_from_string( - addr[1])) - elif self._is_hostmask(addr[1]): - self.netmask = IPv4Address( - self._ip_int_from_string(addr[1]) ^ self._ALL_ONES) - else: - raise NetmaskValueError('%r is not a valid netmask' - % addr[1]) - - self._prefixlen = self._prefix_from_ip_int(int(self.netmask)) - else: - # We have a netmask in prefix length form. - if not self._is_valid_netmask(addr[1]): - raise NetmaskValueError('%r is not a valid netmask' - % addr[1]) - self._prefixlen = int(addr[1]) - self.netmask = IPv4Address(self._ip_int_from_prefix( - self._prefixlen)) + try: + # Check for a netmask in prefix length form + self._prefixlen = self._prefix_from_prefix_string(addr[1]) + except NetmaskValueError: + # Check for a netmask or hostmask in dotted-quad form. + # This may raise NetmaskValueError. + self._prefixlen = self._prefix_from_ip_string(addr[1]) else: self._prefixlen = self._max_prefixlen - self.netmask = IPv4Address(self._ip_int_from_prefix( - self._prefixlen)) + self.netmask = IPv4Address(self._ip_int_from_prefix(self._prefixlen)) if strict: if (IPv4Address(int(self.network_address) & int(self.netmask)) != @@ -2042,11 +2080,8 @@ self.network_address = IPv6Address(self._ip_int_from_string(addr[0])) if len(addr) == 2: - if self._is_valid_netmask(addr[1]): - self._prefixlen = int(addr[1]) - else: - raise NetmaskValueError('%r is not a valid netmask' - % addr[1]) + # This may raise NetmaskValueError + self._prefixlen = self._prefix_from_prefix_string(addr[1]) else: self._prefixlen = self._max_prefixlen @@ -2061,23 +2096,6 @@ if self._prefixlen == (self._max_prefixlen - 1): self.hosts = self.__iter__ - def _is_valid_netmask(self, prefixlen): - """Verify that the netmask/prefixlen is valid. - - Args: - prefixlen: A string, the netmask in prefix length format. - - Returns: - A boolean, True if the prefix represents a valid IPv6 - netmask. - - """ - try: - prefixlen = int(prefixlen) - except ValueError: - return False - return 0 <= prefixlen <= self._max_prefixlen - @property def is_site_local(self): """Test if the address is reserved for site-local. diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -398,18 +398,47 @@ assertBadAddress("::1.2.3.4", "Only decimal digits") assertBadAddress("1.2.3.256", re.escape("256 (> 255)")) + def test_valid_netmask(self): + self.assertEqual(str(self.factory('192.0.2.0/255.255.255.0')), + '192.0.2.0/24') + for i in range(0, 33): + # Generate and re-parse the CIDR format (trivial). + net_str = '0.0.0.0/%d' % i + net = self.factory(net_str) + self.assertEqual(str(net), net_str) + # Generate and re-parse the expanded netmask. + self.assertEqual( + str(self.factory('0.0.0.0/%s' % net.netmask)), net_str) + # Zero prefix is treated as decimal. + self.assertEqual(str(self.factory('0.0.0.0/0%d' % i)), net_str) + # Generate and re-parse the expanded hostmask. The ambiguous + # cases (/0 and /32) are treated as netmasks. + if i in (32, 0): + net_str = '0.0.0.0/%d' % (32 - i) + self.assertEqual( + str(self.factory('0.0.0.0/%s' % net.hostmask)), net_str) + def test_netmask_errors(self): def assertBadNetmask(addr, netmask): - msg = "%r is not a valid netmask" - with self.assertNetmaskError(msg % netmask): + msg = "%r is not a valid netmask" % netmask + with self.assertNetmaskError(re.escape(msg)): self.factory("%s/%s" % (addr, netmask)) assertBadNetmask("1.2.3.4", "") + assertBadNetmask("1.2.3.4", "-1") + assertBadNetmask("1.2.3.4", "+1") + assertBadNetmask("1.2.3.4", " 1 ") + assertBadNetmask("1.2.3.4", "0x1") assertBadNetmask("1.2.3.4", "33") assertBadNetmask("1.2.3.4", "254.254.255.256") + assertBadNetmask("1.2.3.4", "1.a.2.3") assertBadNetmask("1.1.1.1", "254.xyz.2.3") assertBadNetmask("1.1.1.1", "240.255.0.0") + assertBadNetmask("1.1.1.1", "255.254.128.0") + assertBadNetmask("1.1.1.1", "0.1.127.255") assertBadNetmask("1.1.1.1", "pudding") + assertBadNetmask("1.1.1.1", "::") + class InterfaceTestCase_v4(BaseTestCase, NetmaskTestMixin_v4): factory = ipaddress.IPv4Interface @@ -438,17 +467,34 @@ assertBadAddress("10/8", "At least 3 parts") assertBadAddress("1234:axy::b", "Only hex digits") + def test_valid_netmask(self): + # We only support CIDR for IPv6, because expanded netmasks are not + # standard notation. + self.assertEqual(str(self.factory('2001:db8::/32')), '2001:db8::/32') + for i in range(0, 129): + # Generate and re-parse the CIDR format (trivial). + net_str = '::/%d' % i + self.assertEqual(str(self.factory(net_str)), net_str) + # Zero prefix is treated as decimal. + self.assertEqual(str(self.factory('::/0%d' % i)), net_str) + def test_netmask_errors(self): def assertBadNetmask(addr, netmask): - msg = "%r is not a valid netmask" - with self.assertNetmaskError(msg % netmask): + msg = "%r is not a valid netmask" % netmask + with self.assertNetmaskError(re.escape(msg)): self.factory("%s/%s" % (addr, netmask)) assertBadNetmask("::1", "") assertBadNetmask("::1", "::1") assertBadNetmask("::1", "1::") + assertBadNetmask("::1", "-1") + assertBadNetmask("::1", "+1") + assertBadNetmask("::1", " 1 ") + assertBadNetmask("::1", "0x1") assertBadNetmask("::1", "129") + assertBadNetmask("::1", "1.2.3.4") assertBadNetmask("::1", "pudding") + assertBadNetmask("::", "::") class InterfaceTestCase_v6(BaseTestCase, NetmaskTestMixin_v6): factory = ipaddress.IPv6Interface @@ -694,16 +740,14 @@ def testZeroNetmask(self): ipv4_zero_netmask = ipaddress.IPv4Interface('1.2.3.4/0') self.assertEqual(int(ipv4_zero_netmask.network.netmask), 0) - self.assertTrue(ipv4_zero_netmask.network._is_valid_netmask( - str(0))) + self.assertEqual(ipv4_zero_netmask._prefix_from_prefix_string('0'), 0) self.assertTrue(ipv4_zero_netmask._is_valid_netmask('0')) self.assertTrue(ipv4_zero_netmask._is_valid_netmask('0.0.0.0')) self.assertFalse(ipv4_zero_netmask._is_valid_netmask('invalid')) ipv6_zero_netmask = ipaddress.IPv6Interface('::1/0') self.assertEqual(int(ipv6_zero_netmask.network.netmask), 0) - self.assertTrue(ipv6_zero_netmask.network._is_valid_netmask( - str(0))) + self.assertEqual(ipv6_zero_netmask._prefix_from_prefix_string('0'), 0) def testIPv4NetAndHostmasks(self): net = self.ipv4_network @@ -719,7 +763,7 @@ self.assertFalse(net._is_hostmask('1.2.3.4')) net = ipaddress.IPv4Network('127.0.0.0/0.0.0.255') - self.assertEqual(24, net.prefixlen) + self.assertEqual(net.prefixlen, 24) def testGetBroadcast(self): self.assertEqual(int(self.ipv4_network.broadcast_address), 16909311) @@ -1271,11 +1315,6 @@ self.assertEqual(ipaddress.IPv6Interface('::1:0:0:0:0').packed, b'\x00' * 6 + b'\x00\x01' + b'\x00' * 8) - def testIpStrFromPrefixlen(self): - ipv4 = ipaddress.IPv4Interface('1.2.3.4/24') - self.assertEqual(ipv4._ip_string_from_prefix(), '255.255.255.0') - self.assertEqual(ipv4._ip_string_from_prefix(28), '255.255.255.240') - def testIpType(self): ipv4net = ipaddress.ip_network('1.2.3.4') ipv4addr = ipaddress.ip_address('1.2.3.4') @@ -1467,14 +1506,8 @@ def testIPBases(self): net = self.ipv4_network self.assertEqual('1.2.3.0/24', net.compressed) - self.assertEqual( - net._ip_int_from_prefix(24), - net._ip_int_from_prefix(None)) net = self.ipv6_network self.assertRaises(ValueError, net._string_from_ip_int, 2**128 + 1) - self.assertEqual( - self.ipv6_address._string_from_ip_int(self.ipv6_address._ip), - self.ipv6_address._string_from_ip_int(None)) def testIPv6NetworkHelpers(self): net = self.ipv6_network diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,6 +48,9 @@ Library ------- +- Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably + filters out illegal values + - Issue #17369: get_filename was raising an exception if the filename parameter's RFC2231 encoding was broken in certain ways. This was a regression relative to python2. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:21:15 2014 From: python-checkins at python.org (nick.coghlan) Date: Sat, 8 Feb 2014 14:21:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_fix_for_=2318805_from_3=2E3?= Message-ID: <3fLvCb3vSTz7LkD@mail.python.org> http://hg.python.org/cpython/rev/90dfb26869a7 changeset: 89044:90dfb26869a7 parent: 89042:2e5e66f9e228 parent: 89043:ca5ea7c24370 user: Nick Coghlan date: Sat Feb 08 23:20:58 2014 +1000 summary: Merge fix for #18805 from 3.3 files: Lib/ipaddress.py | 148 ++++++++++++++---------- Lib/test/test_ipaddress.py | 73 ++++++++--- Misc/NEWS | 3 + 3 files changed, 139 insertions(+), 85 deletions(-) diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -456,8 +456,8 @@ raise AddressValueError(msg % (address, address_len, expected_len, self._version)) - def _ip_int_from_prefix(self, prefixlen=None): - """Turn the prefix length netmask into a int for comparison. + def _ip_int_from_prefix(self, prefixlen): + """Turn the prefix length into a bitwise netmask Args: prefixlen: An integer, the prefix length. @@ -466,36 +466,92 @@ An integer. """ - if prefixlen is None: - prefixlen = self._prefixlen return self._ALL_ONES ^ (self._ALL_ONES >> prefixlen) - def _prefix_from_ip_int(self, ip_int, mask=32): - """Return prefix length from the decimal netmask. + def _prefix_from_ip_int(self, ip_int): + """Return prefix length from the bitwise netmask. Args: - ip_int: An integer, the IP address. - mask: The netmask. Defaults to 32. + ip_int: An integer, the netmask in axpanded bitwise format Returns: An integer, the prefix length. + Raises: + ValueError: If the input intermingles zeroes & ones """ - return mask - _count_righthand_zero_bits(ip_int, mask) + trailing_zeroes = _count_righthand_zero_bits(ip_int, + self._max_prefixlen) + prefixlen = self._max_prefixlen - trailing_zeroes + leading_ones = ip_int >> trailing_zeroes + all_ones = (1 << prefixlen) - 1 + if leading_ones != all_ones: + byteslen = self._max_prefixlen // 8 + details = ip_int.to_bytes(byteslen, 'big') + msg = 'Netmask pattern %r mixes zeroes & ones' + raise ValueError(msg % details) + return prefixlen - def _ip_string_from_prefix(self, prefixlen=None): - """Turn a prefix length into a dotted decimal string. + def _report_invalid_netmask(self, netmask_str): + msg = '%r is not a valid netmask' % netmask_str + raise NetmaskValueError(msg) from None + + def _prefix_from_prefix_string(self, prefixlen_str): + """Return prefix length from a numeric string Args: - prefixlen: An integer, the netmask prefix length. + prefixlen_str: The string to be converted Returns: - A string, the dotted decimal netmask string. + An integer, the prefix length. + Raises: + NetmaskValueError: If the input is not a valid netmask """ - if not prefixlen: - prefixlen = self._prefixlen - return self._string_from_ip_int(self._ip_int_from_prefix(prefixlen)) + # int allows a leading +/- as well as surrounding whitespace, + # so we ensure that isn't the case + if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str): + self._report_invalid_netmask(prefixlen_str) + try: + prefixlen = int(prefixlen_str) + except ValueError: + self._report_invalid_netmask(prefixlen_str) + if not (0 <= prefixlen <= self._max_prefixlen): + self._report_invalid_netmask(prefixlen_str) + return prefixlen + + def _prefix_from_ip_string(self, ip_str): + """Turn a netmask/hostmask string into a prefix length + + Args: + ip_str: The netmask/hostmask to be converted + + Returns: + An integer, the prefix length. + + Raises: + NetmaskValueError: If the input is not a valid netmask/hostmask + """ + # Parse the netmask/hostmask like an IP address. + try: + ip_int = self._ip_int_from_string(ip_str) + except AddressValueError: + self._report_invalid_netmask(ip_str) + + # Try matching a netmask (this would be /1*0*/ as a bitwise regexp). + # Note that the two ambiguous cases (all-ones and all-zeroes) are + # treated as netmasks. + try: + return self._prefix_from_ip_int(ip_int) + except ValueError: + pass + + # Invert the bits, and try matching a /0+1+/ hostmask instead. + ip_int ^= self._ALL_ONES + try: + return self._prefix_from_ip_int(ip_int) + except ValueError: + self._report_invalid_netmask(ip_str) class _BaseAddress(_IPAddressBase): @@ -504,7 +560,6 @@ This IP class contains the version independent methods which are used by single IP addresses. - """ def __init__(self, address): @@ -873,7 +928,7 @@ raise ValueError('prefix length diff must be > 0') new_prefixlen = self._prefixlen + prefixlen_diff - if not self._is_valid_netmask(str(new_prefixlen)): + if new_prefixlen > self._max_prefixlen: raise ValueError( 'prefix length diff %d is invalid for netblock %s' % ( new_prefixlen, self)) @@ -1451,33 +1506,16 @@ self.network_address = IPv4Address(self._ip_int_from_string(addr[0])) if len(addr) == 2: - mask = addr[1].split('.') - - if len(mask) == 4: - # We have dotted decimal netmask. - if self._is_valid_netmask(addr[1]): - self.netmask = IPv4Address(self._ip_int_from_string( - addr[1])) - elif self._is_hostmask(addr[1]): - self.netmask = IPv4Address( - self._ip_int_from_string(addr[1]) ^ self._ALL_ONES) - else: - raise NetmaskValueError('%r is not a valid netmask' - % addr[1]) - - self._prefixlen = self._prefix_from_ip_int(int(self.netmask)) - else: - # We have a netmask in prefix length form. - if not self._is_valid_netmask(addr[1]): - raise NetmaskValueError('%r is not a valid netmask' - % addr[1]) - self._prefixlen = int(addr[1]) - self.netmask = IPv4Address(self._ip_int_from_prefix( - self._prefixlen)) + try: + # Check for a netmask in prefix length form + self._prefixlen = self._prefix_from_prefix_string(addr[1]) + except NetmaskValueError: + # Check for a netmask or hostmask in dotted-quad form. + # This may raise NetmaskValueError. + self._prefixlen = self._prefix_from_ip_string(addr[1]) else: self._prefixlen = self._max_prefixlen - self.netmask = IPv4Address(self._ip_int_from_prefix( - self._prefixlen)) + self.netmask = IPv4Address(self._ip_int_from_prefix(self._prefixlen)) if strict: if (IPv4Address(int(self.network_address) & int(self.netmask)) != @@ -2101,11 +2139,8 @@ self.network_address = IPv6Address(self._ip_int_from_string(addr[0])) if len(addr) == 2: - if self._is_valid_netmask(addr[1]): - self._prefixlen = int(addr[1]) - else: - raise NetmaskValueError('%r is not a valid netmask' - % addr[1]) + # This may raise NetmaskValueError + self._prefixlen = self._prefix_from_prefix_string(addr[1]) else: self._prefixlen = self._max_prefixlen @@ -2120,23 +2155,6 @@ if self._prefixlen == (self._max_prefixlen - 1): self.hosts = self.__iter__ - def _is_valid_netmask(self, prefixlen): - """Verify that the netmask/prefixlen is valid. - - Args: - prefixlen: A string, the netmask in prefix length format. - - Returns: - A boolean, True if the prefix represents a valid IPv6 - netmask. - - """ - try: - prefixlen = int(prefixlen) - except ValueError: - return False - return 0 <= prefixlen <= self._max_prefixlen - @property def is_site_local(self): """Test if the address is reserved for site-local. diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -398,18 +398,47 @@ assertBadAddress("::1.2.3.4", "Only decimal digits") assertBadAddress("1.2.3.256", re.escape("256 (> 255)")) + def test_valid_netmask(self): + self.assertEqual(str(self.factory('192.0.2.0/255.255.255.0')), + '192.0.2.0/24') + for i in range(0, 33): + # Generate and re-parse the CIDR format (trivial). + net_str = '0.0.0.0/%d' % i + net = self.factory(net_str) + self.assertEqual(str(net), net_str) + # Generate and re-parse the expanded netmask. + self.assertEqual( + str(self.factory('0.0.0.0/%s' % net.netmask)), net_str) + # Zero prefix is treated as decimal. + self.assertEqual(str(self.factory('0.0.0.0/0%d' % i)), net_str) + # Generate and re-parse the expanded hostmask. The ambiguous + # cases (/0 and /32) are treated as netmasks. + if i in (32, 0): + net_str = '0.0.0.0/%d' % (32 - i) + self.assertEqual( + str(self.factory('0.0.0.0/%s' % net.hostmask)), net_str) + def test_netmask_errors(self): def assertBadNetmask(addr, netmask): - msg = "%r is not a valid netmask" - with self.assertNetmaskError(msg % netmask): + msg = "%r is not a valid netmask" % netmask + with self.assertNetmaskError(re.escape(msg)): self.factory("%s/%s" % (addr, netmask)) assertBadNetmask("1.2.3.4", "") + assertBadNetmask("1.2.3.4", "-1") + assertBadNetmask("1.2.3.4", "+1") + assertBadNetmask("1.2.3.4", " 1 ") + assertBadNetmask("1.2.3.4", "0x1") assertBadNetmask("1.2.3.4", "33") assertBadNetmask("1.2.3.4", "254.254.255.256") + assertBadNetmask("1.2.3.4", "1.a.2.3") assertBadNetmask("1.1.1.1", "254.xyz.2.3") assertBadNetmask("1.1.1.1", "240.255.0.0") + assertBadNetmask("1.1.1.1", "255.254.128.0") + assertBadNetmask("1.1.1.1", "0.1.127.255") assertBadNetmask("1.1.1.1", "pudding") + assertBadNetmask("1.1.1.1", "::") + class InterfaceTestCase_v4(BaseTestCase, NetmaskTestMixin_v4): factory = ipaddress.IPv4Interface @@ -438,17 +467,34 @@ assertBadAddress("10/8", "At least 3 parts") assertBadAddress("1234:axy::b", "Only hex digits") + def test_valid_netmask(self): + # We only support CIDR for IPv6, because expanded netmasks are not + # standard notation. + self.assertEqual(str(self.factory('2001:db8::/32')), '2001:db8::/32') + for i in range(0, 129): + # Generate and re-parse the CIDR format (trivial). + net_str = '::/%d' % i + self.assertEqual(str(self.factory(net_str)), net_str) + # Zero prefix is treated as decimal. + self.assertEqual(str(self.factory('::/0%d' % i)), net_str) + def test_netmask_errors(self): def assertBadNetmask(addr, netmask): - msg = "%r is not a valid netmask" - with self.assertNetmaskError(msg % netmask): + msg = "%r is not a valid netmask" % netmask + with self.assertNetmaskError(re.escape(msg)): self.factory("%s/%s" % (addr, netmask)) assertBadNetmask("::1", "") assertBadNetmask("::1", "::1") assertBadNetmask("::1", "1::") + assertBadNetmask("::1", "-1") + assertBadNetmask("::1", "+1") + assertBadNetmask("::1", " 1 ") + assertBadNetmask("::1", "0x1") assertBadNetmask("::1", "129") + assertBadNetmask("::1", "1.2.3.4") assertBadNetmask("::1", "pudding") + assertBadNetmask("::", "::") class InterfaceTestCase_v6(BaseTestCase, NetmaskTestMixin_v6): factory = ipaddress.IPv6Interface @@ -694,16 +740,14 @@ def testZeroNetmask(self): ipv4_zero_netmask = ipaddress.IPv4Interface('1.2.3.4/0') self.assertEqual(int(ipv4_zero_netmask.network.netmask), 0) - self.assertTrue(ipv4_zero_netmask.network._is_valid_netmask( - str(0))) + self.assertEqual(ipv4_zero_netmask._prefix_from_prefix_string('0'), 0) self.assertTrue(ipv4_zero_netmask._is_valid_netmask('0')) self.assertTrue(ipv4_zero_netmask._is_valid_netmask('0.0.0.0')) self.assertFalse(ipv4_zero_netmask._is_valid_netmask('invalid')) ipv6_zero_netmask = ipaddress.IPv6Interface('::1/0') self.assertEqual(int(ipv6_zero_netmask.network.netmask), 0) - self.assertTrue(ipv6_zero_netmask.network._is_valid_netmask( - str(0))) + self.assertEqual(ipv6_zero_netmask._prefix_from_prefix_string('0'), 0) def testIPv4NetAndHostmasks(self): net = self.ipv4_network @@ -719,7 +763,7 @@ self.assertFalse(net._is_hostmask('1.2.3.4')) net = ipaddress.IPv4Network('127.0.0.0/0.0.0.255') - self.assertEqual(24, net.prefixlen) + self.assertEqual(net.prefixlen, 24) def testGetBroadcast(self): self.assertEqual(int(self.ipv4_network.broadcast_address), 16909311) @@ -1271,11 +1315,6 @@ self.assertEqual(ipaddress.IPv6Interface('::1:0:0:0:0').packed, b'\x00' * 6 + b'\x00\x01' + b'\x00' * 8) - def testIpStrFromPrefixlen(self): - ipv4 = ipaddress.IPv4Interface('1.2.3.4/24') - self.assertEqual(ipv4._ip_string_from_prefix(), '255.255.255.0') - self.assertEqual(ipv4._ip_string_from_prefix(28), '255.255.255.240') - def testIpType(self): ipv4net = ipaddress.ip_network('1.2.3.4') ipv4addr = ipaddress.ip_address('1.2.3.4') @@ -1479,14 +1518,8 @@ def testIPBases(self): net = self.ipv4_network self.assertEqual('1.2.3.0/24', net.compressed) - self.assertEqual( - net._ip_int_from_prefix(24), - net._ip_int_from_prefix(None)) net = self.ipv6_network self.assertRaises(ValueError, net._string_from_ip_int, 2**128 + 1) - self.assertEqual( - self.ipv6_address._string_from_ip_int(self.ipv6_address._ip), - self.ipv6_address._string_from_ip_int(None)) def testIPv6NetworkHelpers(self): net = self.ipv6_network diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,9 @@ Library ------- +- Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably + filters out illegal values + - Issue #20481: For at least Python 3.4, the statistics module will require that all inputs for a single operation be of a single consistent type, or else a mixed of ints and a single other consistent type. This avoids -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:40:38 2014 From: python-checkins at python.org (nick.coghlan) Date: Sat, 8 Feb 2014 14:40:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogRml4ICMxODgwNSBO?= =?utf-8?q?EWS_entry?= Message-ID: <3fLvdy0xZgz7Ljm@mail.python.org> http://hg.python.org/cpython/rev/19ca11099f07 changeset: 89045:19ca11099f07 branch: 3.3 parent: 89043:ca5ea7c24370 user: Nick Coghlan date: Sat Feb 08 23:39:54 2014 +1000 summary: Fix #18805 NEWS entry files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -49,7 +49,7 @@ ------- - Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably - filters out illegal values + filters out illegal values and correctly allows any valid prefix length. - Issue #17369: get_filename was raising an exception if the filename parameter's RFC2231 encoding was broken in certain ways. This was -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:40:39 2014 From: python-checkins at python.org (nick.coghlan) Date: Sat, 8 Feb 2014 14:40:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_=2318805_NEWS_fix_from_3=2E3?= Message-ID: <3fLvdz2vM0z7Ln4@mail.python.org> http://hg.python.org/cpython/rev/e0b1c937e57c changeset: 89046:e0b1c937e57c parent: 89044:90dfb26869a7 parent: 89045:19ca11099f07 user: Nick Coghlan date: Sat Feb 08 23:40:23 2014 +1000 summary: Merge #18805 NEWS fix from 3.3 files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,7 +28,7 @@ ------- - Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably - filters out illegal values + filters out illegal values and correctly allows any valid prefix length. - Issue #20481: For at least Python 3.4, the statistics module will require that all inputs for a single operation be of a single consistent type, or -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 14:55:27 2014 From: python-checkins at python.org (nick.coghlan) Date: Sat, 8 Feb 2014 14:55:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320536=3A_correctl?= =?utf-8?q?y_handle_Decimal_exponents_in_statistics?= Message-ID: <3fLvz3181Qz7Ljm@mail.python.org> http://hg.python.org/cpython/rev/0f9309f8c755 changeset: 89047:0f9309f8c755 user: Nick Coghlan date: Sat Feb 08 23:55:14 2014 +1000 summary: Close #20536: correctly handle Decimal exponents in statistics files: Lib/statistics.py | 6 +++- Lib/test/test_statistics.py | 38 +++++++++++++++++++++++++ Misc/NEWS | 3 + 3 files changed, 46 insertions(+), 1 deletions(-) diff --git a/Lib/statistics.py b/Lib/statistics.py --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -243,9 +243,13 @@ num = 0 for digit in digits: num = num*10 + digit + if exp < 0: + den = 10**-exp + else: + num *= 10**exp + den = 1 if sign: num = -num - den = 10**-exp return (num, den) diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -686,6 +686,38 @@ for d in (Decimal('NAN'), Decimal('sNAN'), Decimal('INF')): self.assertRaises(ValueError, statistics._decimal_to_ratio, d) + def test_sign(self): + # Test sign is calculated correctly. + numbers = [Decimal("9.8765e12"), Decimal("9.8765e-12")] + for d in numbers: + # First test positive decimals. + assert d > 0 + num, den = statistics._decimal_to_ratio(d) + self.assertGreaterEqual(num, 0) + self.assertGreater(den, 0) + # Then test negative decimals. + num, den = statistics._decimal_to_ratio(-d) + self.assertLessEqual(num, 0) + self.assertGreater(den, 0) + + def test_negative_exponent(self): + # Test result when the exponent is negative. + t = statistics._decimal_to_ratio(Decimal("0.1234")) + self.assertEqual(t, (1234, 10000)) + + def test_positive_exponent(self): + # Test results when the exponent is positive. + t = statistics._decimal_to_ratio(Decimal("1.234e7")) + self.assertEqual(t, (12340000, 1)) + + def test_regression_20536(self): + # Regression test for issue 20536. + # See http://bugs.python.org/issue20536 + t = statistics._decimal_to_ratio(Decimal("1e2")) + self.assertEqual(t, (100, 1)) + t = statistics._decimal_to_ratio(Decimal("1.47e5")) + self.assertEqual(t, (147000, 1)) + class CheckTypeTest(unittest.TestCase): # Test _check_type private function. @@ -1074,6 +1106,12 @@ actual = self.func(data*2) self.assertApproxEqual(actual, expected) + def test_regression_20561(self): + # Regression test for issue 20561. + # See http://bugs.python.org/issue20561 + d = Decimal('1e4') + self.assertEqual(statistics.mean([d]), d) + class TestMedian(NumericTestCase, AverageMixin): # Common tests for median and all median.* functions. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,9 @@ Library ------- +- Issue #20536: the statistics module now correctly handle Decimal instances + with positive exponents + - Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably filters out illegal values and correctly allows any valid prefix length. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 15:05:55 2014 From: python-checkins at python.org (terry.reedy) Date: Sat, 8 Feb 2014 15:05:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNDA2?= =?utf-8?q?=3A_Use_Python_application_icons_for_Idle_window_title_bars=2E?= Message-ID: <3fLwC71fyNz7LkD@mail.python.org> http://hg.python.org/cpython/rev/bda1739215b4 changeset: 89048:bda1739215b4 branch: 3.3 parent: 89045:19ca11099f07 user: Terry Jan Reedy date: Sat Feb 08 09:02:26 2014 -0500 summary: Issue #20406: Use Python application icons for Idle window title bars. Patch mostly by Serhiy Storchaka. files: Lib/idlelib/Icons/idle.ico | Bin Lib/idlelib/Icons/idle_16.gif | Bin Lib/idlelib/Icons/idle_16.png | Bin Lib/idlelib/Icons/idle_32.gif | Bin Lib/idlelib/Icons/idle_32.png | Bin Lib/idlelib/Icons/idle_48.gif | Bin Lib/idlelib/Icons/idle_48.png | Bin Lib/idlelib/PyShell.py | 14 +++++++++++++- Misc/NEWS | 3 +++ 9 files changed, 16 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/Icons/idle.ico b/Lib/idlelib/Icons/idle.ico new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3357aef14888c501bcd7bfe02393760306a18d06 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_16.gif b/Lib/idlelib/Icons/idle_16.gif new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9f001b1d79cf697bb81bde59a5bc2f8341f74ba6 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_16.png b/Lib/idlelib/Icons/idle_16.png new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6abde0af90cb6bc9dfc71cc4d8fd17abc3c7bf53 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_32.gif b/Lib/idlelib/Icons/idle_32.gif new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..af5b2d52cce8951a47ac1604b9332b9032c0ce2d GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_32.png b/Lib/idlelib/Icons/idle_32.png new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..41b70dbc37766a9f229f4e0b88ddc2f13d22e3db GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_48.gif b/Lib/idlelib/Icons/idle_48.gif new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fc5304f31eed32d5f7769e471c3817b58edc10e4 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_48.png b/Lib/idlelib/Icons/idle_48.png new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e5fa9280e21f86b0e5e750b02279b93e36009589 GIT binary patch [stripped] diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -16,7 +16,7 @@ import linecache from code import InteractiveInterpreter -from platform import python_version +from platform import python_version, system try: from tkinter import * @@ -1524,6 +1524,18 @@ # start editor and/or shell windows: root = Tk(className="Idle") + # set application icon + icondir = os.path.join(os.path.dirname(__file__), 'Icons') + if system() == 'Windows': + iconfile = os.path.join(icondir, 'idle.ico') + root.wm_iconbitmap(default=iconfile) + elif TkVersion >= 8.5: + ext = '.png' if TkVersion >= 8.6 else '.gif' + iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext)) + for size in (16, 32, 48)] + icons = [PhotoImage(file=iconfile) for iconfile in iconfiles] + root.wm_iconphoto(True, *icons) + fixwordbreaks(root) root.withdraw() flist = PyShellFileList(root) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -316,6 +316,9 @@ IDLE ---- +- Issue #20406: Use Python application icons for Idle window title bars. + Patch mostly by Serhiy Storchaka. + - Update the python.gif icon for the Idle classbrowser and pathbowser from the old green snake to the new new blue and yellow snakes. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 15:05:56 2014 From: python-checkins at python.org (terry.reedy) Date: Sat, 8 Feb 2014 15:05:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320406=3A_Use_Python_application_icons_for_Idle_?= =?utf-8?q?window_title_bars=2E?= Message-ID: <3fLwC84gbXz7Lnl@mail.python.org> http://hg.python.org/cpython/rev/3aa6fd1dc2c9 changeset: 89049:3aa6fd1dc2c9 parent: 89047:0f9309f8c755 parent: 89048:bda1739215b4 user: Terry Jan Reedy date: Sat Feb 08 09:05:20 2014 -0500 summary: Issue #20406: Use Python application icons for Idle window title bars. Patch mostly by Serhiy Storchaka. files: Lib/idlelib/Icons/idle.ico | Bin Lib/idlelib/Icons/idle_16.gif | Bin Lib/idlelib/Icons/idle_16.png | Bin Lib/idlelib/Icons/idle_32.gif | Bin Lib/idlelib/Icons/idle_32.png | Bin Lib/idlelib/Icons/idle_48.gif | Bin Lib/idlelib/Icons/idle_48.png | Bin Lib/idlelib/PyShell.py | 14 +++++++++++++- Misc/NEWS | 3 +++ 9 files changed, 16 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/Icons/idle.ico b/Lib/idlelib/Icons/idle.ico new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3357aef14888c501bcd7bfe02393760306a18d06 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_16.gif b/Lib/idlelib/Icons/idle_16.gif new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9f001b1d79cf697bb81bde59a5bc2f8341f74ba6 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_16.png b/Lib/idlelib/Icons/idle_16.png new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6abde0af90cb6bc9dfc71cc4d8fd17abc3c7bf53 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_32.gif b/Lib/idlelib/Icons/idle_32.gif new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..af5b2d52cce8951a47ac1604b9332b9032c0ce2d GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_32.png b/Lib/idlelib/Icons/idle_32.png new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..41b70dbc37766a9f229f4e0b88ddc2f13d22e3db GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_48.gif b/Lib/idlelib/Icons/idle_48.gif new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fc5304f31eed32d5f7769e471c3817b58edc10e4 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_48.png b/Lib/idlelib/Icons/idle_48.png new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e5fa9280e21f86b0e5e750b02279b93e36009589 GIT binary patch [stripped] diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -16,7 +16,7 @@ import linecache from code import InteractiveInterpreter -from platform import python_version +from platform import python_version, system try: from tkinter import * @@ -1530,6 +1530,18 @@ # start editor and/or shell windows: root = Tk(className="Idle") + # set application icon + icondir = os.path.join(os.path.dirname(__file__), 'Icons') + if system() == 'Windows': + iconfile = os.path.join(icondir, 'idle.ico') + root.wm_iconbitmap(default=iconfile) + elif TkVersion >= 8.5: + ext = '.png' if TkVersion >= 8.6 else '.gif' + iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext)) + for size in (16, 32, 48)] + icons = [PhotoImage(file=iconfile) for iconfile in iconfiles] + root.wm_iconphoto(True, *icons) + fixwordbreaks(root) root.withdraw() flist = PyShellFileList(root) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -156,6 +156,9 @@ IDLE ---- +- Issue #20406: Use Python application icons for Idle window title bars. + Patch mostly by Serhiy Storchaka. + - Update the python.gif icon for the Idle classbrowser and pathbowser from the old green snake to the new new blue and yellow snakes. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 15:40:26 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 15:40:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTUz?= =?utf-8?q?=2E_Use_specific_asserts_in_ipaddress_tests=2E?= Message-ID: <3fLwyy0sMZz7LjM@mail.python.org> http://hg.python.org/cpython/rev/58be80e7e653 changeset: 89050:58be80e7e653 branch: 3.3 parent: 89048:bda1739215b4 user: Serhiy Storchaka date: Sat Feb 08 16:38:35 2014 +0200 summary: Issue #20553. Use specific asserts in ipaddress tests. files: Lib/test/test_ipaddress.py | 35 ++++++++++++------------- 1 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -921,13 +921,13 @@ 36893488147419103232) def testContains(self): - self.assertTrue(ipaddress.IPv4Interface('1.2.3.128/25') in - self.ipv4_network) - self.assertFalse(ipaddress.IPv4Interface('1.2.4.1/24') in + self.assertIn(ipaddress.IPv4Interface('1.2.3.128/25'), + self.ipv4_network) + self.assertNotIn(ipaddress.IPv4Interface('1.2.4.1/24'), self.ipv4_network) # We can test addresses and string as well. addr1 = ipaddress.IPv4Address('1.2.3.37') - self.assertTrue(addr1 in self.ipv4_network) + self.assertIn(addr1, self.ipv4_network) # issue 61, bad network comparison on like-ip'd network objects # with identical broadcast addresses. self.assertFalse(ipaddress.IPv4Network('1.1.0.0/16').__contains__( @@ -1500,8 +1500,8 @@ dummy[self.ipv6_address] = None dummy[ip1] = None dummy[ip2] = None - self.assertTrue(self.ipv4_address in dummy) - self.assertTrue(ip2 in dummy) + self.assertIn(self.ipv4_address, dummy) + self.assertIn(ip2, dummy) def testIPBases(self): net = self.ipv4_network @@ -1608,9 +1608,9 @@ def testNetworkElementCaching(self): # V4 - make sure we're empty - self.assertFalse('network_address' in self.ipv4_network._cache) - self.assertFalse('broadcast_address' in self.ipv4_network._cache) - self.assertFalse('hostmask' in self.ipv4_network._cache) + self.assertNotIn('network_address', self.ipv4_network._cache) + self.assertNotIn('broadcast_address', self.ipv4_network._cache) + self.assertNotIn('hostmask', self.ipv4_network._cache) # V4 - populate and test self.assertEqual(self.ipv4_network.network_address, @@ -1621,12 +1621,12 @@ ipaddress.IPv4Address('0.0.0.255')) # V4 - check we're cached - self.assertTrue('broadcast_address' in self.ipv4_network._cache) - self.assertTrue('hostmask' in self.ipv4_network._cache) + self.assertIn('broadcast_address', self.ipv4_network._cache) + self.assertIn('hostmask', self.ipv4_network._cache) # V6 - make sure we're empty - self.assertFalse('broadcast_address' in self.ipv6_network._cache) - self.assertFalse('hostmask' in self.ipv6_network._cache) + self.assertNotIn('broadcast_address', self.ipv6_network._cache) + self.assertNotIn('hostmask', self.ipv6_network._cache) # V6 - populate and test self.assertEqual(self.ipv6_network.network_address, @@ -1646,11 +1646,10 @@ ipaddress.IPv6Address('::ffff:ffff:ffff:ffff')) # V6 - check we're cached - self.assertTrue('broadcast_address' in self.ipv6_network._cache) - self.assertTrue('hostmask' in self.ipv6_network._cache) - self.assertTrue( - 'broadcast_address' in self.ipv6_interface.network._cache) - self.assertTrue('hostmask' in self.ipv6_interface.network._cache) + self.assertIn('broadcast_address', self.ipv6_network._cache) + self.assertIn('hostmask', self.ipv6_network._cache) + self.assertIn('broadcast_address', self.ipv6_interface.network._cache) + self.assertIn('hostmask', self.ipv6_interface.network._cache) def testTeredo(self): # stolen from wikipedia -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 15:40:27 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 8 Feb 2014 15:40:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320553=2E_Use_specific_asserts_in_ipaddress_test?= =?utf-8?q?s=2E?= Message-ID: <3fLwyz3Bfhz7LmZ@mail.python.org> http://hg.python.org/cpython/rev/2bcb574d579f changeset: 89051:2bcb574d579f parent: 89049:3aa6fd1dc2c9 parent: 89050:58be80e7e653 user: Serhiy Storchaka date: Sat Feb 08 16:39:51 2014 +0200 summary: Issue #20553. Use specific asserts in ipaddress tests. files: Lib/test/test_ipaddress.py | 35 ++++++++++++------------- 1 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -921,13 +921,13 @@ 36893488147419103232) def testContains(self): - self.assertTrue(ipaddress.IPv4Interface('1.2.3.128/25') in - self.ipv4_network) - self.assertFalse(ipaddress.IPv4Interface('1.2.4.1/24') in + self.assertIn(ipaddress.IPv4Interface('1.2.3.128/25'), + self.ipv4_network) + self.assertNotIn(ipaddress.IPv4Interface('1.2.4.1/24'), self.ipv4_network) # We can test addresses and string as well. addr1 = ipaddress.IPv4Address('1.2.3.37') - self.assertTrue(addr1 in self.ipv4_network) + self.assertIn(addr1, self.ipv4_network) # issue 61, bad network comparison on like-ip'd network objects # with identical broadcast addresses. self.assertFalse(ipaddress.IPv4Network('1.1.0.0/16').__contains__( @@ -1512,8 +1512,8 @@ dummy[self.ipv6_address] = None dummy[ip1] = None dummy[ip2] = None - self.assertTrue(self.ipv4_address in dummy) - self.assertTrue(ip2 in dummy) + self.assertIn(self.ipv4_address, dummy) + self.assertIn(ip2, dummy) def testIPBases(self): net = self.ipv4_network @@ -1620,9 +1620,9 @@ def testNetworkElementCaching(self): # V4 - make sure we're empty - self.assertFalse('network_address' in self.ipv4_network._cache) - self.assertFalse('broadcast_address' in self.ipv4_network._cache) - self.assertFalse('hostmask' in self.ipv4_network._cache) + self.assertNotIn('network_address', self.ipv4_network._cache) + self.assertNotIn('broadcast_address', self.ipv4_network._cache) + self.assertNotIn('hostmask', self.ipv4_network._cache) # V4 - populate and test self.assertEqual(self.ipv4_network.network_address, @@ -1633,12 +1633,12 @@ ipaddress.IPv4Address('0.0.0.255')) # V4 - check we're cached - self.assertTrue('broadcast_address' in self.ipv4_network._cache) - self.assertTrue('hostmask' in self.ipv4_network._cache) + self.assertIn('broadcast_address', self.ipv4_network._cache) + self.assertIn('hostmask', self.ipv4_network._cache) # V6 - make sure we're empty - self.assertFalse('broadcast_address' in self.ipv6_network._cache) - self.assertFalse('hostmask' in self.ipv6_network._cache) + self.assertNotIn('broadcast_address', self.ipv6_network._cache) + self.assertNotIn('hostmask', self.ipv6_network._cache) # V6 - populate and test self.assertEqual(self.ipv6_network.network_address, @@ -1658,11 +1658,10 @@ ipaddress.IPv6Address('::ffff:ffff:ffff:ffff')) # V6 - check we're cached - self.assertTrue('broadcast_address' in self.ipv6_network._cache) - self.assertTrue('hostmask' in self.ipv6_network._cache) - self.assertTrue( - 'broadcast_address' in self.ipv6_interface.network._cache) - self.assertTrue('hostmask' in self.ipv6_interface.network._cache) + self.assertIn('broadcast_address', self.ipv6_network._cache) + self.assertIn('hostmask', self.ipv6_network._cache) + self.assertIn('broadcast_address', self.ipv6_interface.network._cache) + self.assertIn('hostmask', self.ipv6_interface.network._cache) def testTeredo(self): # stolen from wikipedia -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 15:42:47 2014 From: python-checkins at python.org (terry.reedy) Date: Sat, 8 Feb 2014 15:42:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNDA2?= =?utf-8?q?=3A_Use_Python_application_icons_for_Idle_window_title_bars=2E?= Message-ID: <3fLx1g5kPWz7LmZ@mail.python.org> http://hg.python.org/cpython/rev/d4f9efd4be7d changeset: 89052:d4f9efd4be7d branch: 2.7 parent: 89040:1c3fcba31708 user: Terry Jan Reedy date: Sat Feb 08 09:39:51 2014 -0500 summary: Issue #20406: Use Python application icons for Idle window title bars. Patch mostly by Serhiy Storchaka. files: Lib/idlelib/Icons/idle.ico | Bin Lib/idlelib/Icons/idle_16.gif | Bin Lib/idlelib/Icons/idle_16.png | Bin Lib/idlelib/Icons/idle_32.gif | Bin Lib/idlelib/Icons/idle_32.png | Bin Lib/idlelib/Icons/idle_48.gif | Bin Lib/idlelib/Icons/idle_48.png | Bin Lib/idlelib/PyShell.py | 14 +++++++++++++- Misc/NEWS | 3 +++ 9 files changed, 16 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/Icons/idle.ico b/Lib/idlelib/Icons/idle.ico new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3357aef14888c501bcd7bfe02393760306a18d06 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_16.gif b/Lib/idlelib/Icons/idle_16.gif new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9f001b1d79cf697bb81bde59a5bc2f8341f74ba6 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_16.png b/Lib/idlelib/Icons/idle_16.png new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6abde0af90cb6bc9dfc71cc4d8fd17abc3c7bf53 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_32.gif b/Lib/idlelib/Icons/idle_32.gif new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..af5b2d52cce8951a47ac1604b9332b9032c0ce2d GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_32.png b/Lib/idlelib/Icons/idle_32.png new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..41b70dbc37766a9f229f4e0b88ddc2f13d22e3db GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_48.gif b/Lib/idlelib/Icons/idle_48.gif new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fc5304f31eed32d5f7769e471c3817b58edc10e4 GIT binary patch [stripped] diff --git a/Lib/idlelib/Icons/idle_48.png b/Lib/idlelib/Icons/idle_48.png new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e5fa9280e21f86b0e5e750b02279b93e36009589 GIT binary patch [stripped] diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -15,7 +15,7 @@ import linecache from code import InteractiveInterpreter -from platform import python_version +from platform import python_version, system try: from Tkinter import * @@ -1536,6 +1536,18 @@ # start editor and/or shell windows: root = Tk(className="Idle") + # set application icon + icondir = os.path.join(os.path.dirname(__file__), 'Icons') + if system() == 'Windows': + iconfile = os.path.join(icondir, 'idle.ico') + root.wm_iconbitmap(default=iconfile) + elif TkVersion >= 8.5: + ext = '.png' if TkVersion >= 8.6 else '.gif' + iconfiles = [os.path.join(icondir, 'idle_%d%s' % (size, ext)) + for size in (16, 32, 48)] + icons = [PhotoImage(file=iconfile) for iconfile in iconfiles] + root.tk.call('wm', 'iconphoto', str(root), "-default", *icons) + fixwordbreaks(root) root.withdraw() flist = PyShellFileList(root) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -211,6 +211,9 @@ IDLE ---- +- Issue #20406: Use Python application icons for Idle window title bars. + Patch mostly by Serhiy Storchaka. + - Issue #17721: Remove non-functional configuration dialog help button until we make it actually gives some help when clicked. Patch by Guilherme Sim?es. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 17:51:48 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Feb 2014 17:51:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE5NzcyOiBEbyBu?= =?utf-8?q?ot_mutate_message_when_downcoding_to_7bit=2E?= Message-ID: <3fLztX4gZ3z7Ljm@mail.python.org> http://hg.python.org/cpython/rev/34fb36972f8d changeset: 89053:34fb36972f8d branch: 3.3 parent: 89050:58be80e7e653 user: R David Murray date: Sat Feb 08 11:48:20 2014 -0500 summary: #19772: Do not mutate message when downcoding to 7bit. This is a bit of an ugly hack because of the way generator pieces together the output message. The deepcopys aren't too expensive, though, because we know it is only called on messages that are not multiparts, and the payload (the thing that could be large) is an immutable object. Test and preliminary work on patch by Vajrasky Kok. files: Lib/email/generator.py | 14 ++++++++++++++ Lib/test/test_email/test_email.py | 12 +++++++++++- Misc/NEWS | 3 +++ 3 files changed, 28 insertions(+), 1 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -12,6 +12,7 @@ import random import warnings +from copy import deepcopy from io import StringIO, BytesIO from email._policybase import compat32 from email.header import Header @@ -173,10 +174,18 @@ # necessary. oldfp = self._fp try: + self._munge_cte = None self._fp = sfp = self._new_buffer() self._dispatch(msg) finally: self._fp = oldfp + munge_cte = self._munge_cte + del self._munge_cte + # If we munged the cte, copy the message again and re-fix the CTE. + if munge_cte: + msg = deepcopy(msg) + msg.replace_header('content-transfer-encoding', munge_cte[0]) + msg.replace_header('content-type', munge_cte[1]) # Write the headers. First we see if the message object wants to # handle that itself. If not, we'll do it generically. meth = getattr(msg, '_write_headers', None) @@ -225,9 +234,14 @@ if _has_surrogates(msg._payload): charset = msg.get_param('charset') if charset is not None: + # XXX: This copy stuff is an ugly hack to avoid modifying the + # existing message. + msg = deepcopy(msg) del msg['content-transfer-encoding'] msg.set_payload(payload, charset) payload = msg.get_payload() + self._munge_cte = (msg['content-transfer-encoding'], + msg['content-type']) if self._mangle_from_: payload = fcre.sub('>From ', payload) self._write_lines(payload) diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3495,7 +3495,7 @@ self.assertTrue(msg.get_payload(0).get_payload().endswith('\r\n')) -class Test8BitBytesHandling(unittest.TestCase): +class Test8BitBytesHandling(TestEmailBase): # In Python3 all input is string, but that doesn't work if the actual input # uses an 8bit transfer encoding. To hack around that, in email 5.1 we # decode byte streams using the surrogateescape error handler, and @@ -3748,6 +3748,16 @@ email.generator.Generator(out).flatten(msg) self.assertEqual(out.getvalue(), self.non_latin_bin_msg_as7bit_wrapped) + def test_str_generator_should_not_mutate_msg_when_handling_8bit(self): + msg = email.message_from_bytes(self.non_latin_bin_msg) + out = BytesIO() + BytesGenerator(out).flatten(msg) + orig_value = out.getvalue() + Generator(StringIO()).flatten(msg) # Should not mutate msg! + out = BytesIO() + BytesGenerator(out).flatten(msg) + self.assertEqual(out.getvalue(), orig_value) + def test_bytes_generator_with_unix_from(self): # The unixfrom contains a current date, so we can't check it # literally. Just make sure the first word is 'From' and the diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,6 +48,9 @@ Library ------- +- Issue #19772: email.generator no longer mutates the message object when + doing a down-transform from 8bit to 7bit CTEs. + - Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably filters out illegal values and correctly allows any valid prefix length. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 17:51:50 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Feb 2014 17:51:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_=2319772=3A_Do_not_mutate_message_when_downcoding_?= =?utf-8?q?to_7bit=2E?= Message-ID: <3fLztZ05Frz7LkV@mail.python.org> http://hg.python.org/cpython/rev/2e97d3500970 changeset: 89054:2e97d3500970 parent: 89051:2bcb574d579f parent: 89053:34fb36972f8d user: R David Murray date: Sat Feb 08 11:51:18 2014 -0500 summary: Merge #19772: Do not mutate message when downcoding to 7bit. files: Lib/email/generator.py | 14 ++++++++++ Lib/test/test_email/test_contentmanager.py | 2 +- Lib/test/test_email/test_email.py | 12 +++++++- Misc/NEWS | 3 ++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -12,6 +12,7 @@ import random import warnings +from copy import deepcopy from io import StringIO, BytesIO from email._policybase import compat32 from email.header import Header @@ -173,10 +174,18 @@ # necessary. oldfp = self._fp try: + self._munge_cte = None self._fp = sfp = self._new_buffer() self._dispatch(msg) finally: self._fp = oldfp + munge_cte = self._munge_cte + del self._munge_cte + # If we munged the cte, copy the message again and re-fix the CTE. + if munge_cte: + msg = deepcopy(msg) + msg.replace_header('content-transfer-encoding', munge_cte[0]) + msg.replace_header('content-type', munge_cte[1]) # Write the headers. First we see if the message object wants to # handle that itself. If not, we'll do it generically. meth = getattr(msg, '_write_headers', None) @@ -225,9 +234,14 @@ if _has_surrogates(msg._payload): charset = msg.get_param('charset') if charset is not None: + # XXX: This copy stuff is an ugly hack to avoid modifying the + # existing message. + msg = deepcopy(msg) del msg['content-transfer-encoding'] msg.set_payload(payload, charset) payload = msg.get_payload() + self._munge_cte = (msg['content-transfer-encoding'], + msg['content-type']) if self._mangle_from_: payload = fcre.sub('>From ', payload) self._write_lines(payload) diff --git a/Lib/test/test_email/test_contentmanager.py b/Lib/test/test_email/test_contentmanager.py --- a/Lib/test/test_email/test_contentmanager.py +++ b/Lib/test/test_email/test_contentmanager.py @@ -536,8 +536,8 @@ From: victim at monty.org Subject: Help Content-Type: text/plain; charset="utf-8" + Content-Transfer-Encoding: base64 MIME-Version: 1.0 - Content-Transfer-Encoding: base64 aidhaSB1biBwcm9ibMOobWUgZGUgcHl0aG9uLiBpbCBlc3Qgc29ydGkgZGUgc29uIHZpdmFyaXVt Lgo= diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -3529,7 +3529,7 @@ self.assertTrue(msg.get_payload(0).get_payload().endswith('\r\n')) -class Test8BitBytesHandling(unittest.TestCase): +class Test8BitBytesHandling(TestEmailBase): # In Python3 all input is string, but that doesn't work if the actual input # uses an 8bit transfer encoding. To hack around that, in email 5.1 we # decode byte streams using the surrogateescape error handler, and @@ -3782,6 +3782,16 @@ email.generator.Generator(out).flatten(msg) self.assertEqual(out.getvalue(), self.non_latin_bin_msg_as7bit_wrapped) + def test_str_generator_should_not_mutate_msg_when_handling_8bit(self): + msg = email.message_from_bytes(self.non_latin_bin_msg) + out = BytesIO() + BytesGenerator(out).flatten(msg) + orig_value = out.getvalue() + Generator(StringIO()).flatten(msg) # Should not mutate msg! + out = BytesIO() + BytesGenerator(out).flatten(msg) + self.assertEqual(out.getvalue(), orig_value) + def test_bytes_generator_with_unix_from(self): # The unixfrom contains a current date, so we can't check it # literally. Just make sure the first word is 'From' and the diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,9 @@ Library ------- +- Issue #19772: email.generator no longer mutates the message object when + doing a down-transform from 8bit to 7bit CTEs. + - Issue #20536: the statistics module now correctly handle Decimal instances with positive exponents -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 19:13:51 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Feb 2014 19:13:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE2OTgzOiBBcHBs?= =?utf-8?q?y_postel=27s_law_to_encoded_words_inside_quoted_strings=2E?= Message-ID: <3fM1jC3GGrz7LkF@mail.python.org> http://hg.python.org/cpython/rev/1dcb9d0d53a6 changeset: 89055:1dcb9d0d53a6 branch: 3.3 parent: 89053:34fb36972f8d user: R David Murray date: Sat Feb 08 13:12:00 2014 -0500 summary: #16983: Apply postel's law to encoded words inside quoted strings. This applies only to the new parser. The old parser decodes encoded words inside quoted strings already, although it gets the whitespace wrong when it does so. This version of the patch only handles the most common case (a single encoded word surrounded by quotes), but I haven't seen any other variations of this in the wild yet, so its good enough for now. files: Lib/email/_header_value_parser.py | 7 +++++++ Lib/test/test_email/test__header_value_parser.py | 9 +++++++++ Lib/test/test_email/test_headerregistry.py | 10 ++++++++++ Misc/NEWS | 3 +++ 4 files changed, 29 insertions(+), 0 deletions(-) diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1559,6 +1559,13 @@ while value and value[0] != '"': if value[0] in WSP: token, value = get_fws(value) + elif value[:2] == '=?': + try: + token, value = get_encoded_word(value) + bare_quoted_string.defects.append(errors.InvalidHeaderDefect( + "encoded word inside quoted string")) + except errors.HeaderParseError: + token, value = get_qcontent(value) else: token, value = get_qcontent(value) bare_quoted_string.append(token) diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -540,6 +540,15 @@ self._test_get_x(parser.get_bare_quoted_string, '""', '""', '', [], '') + # Issue 16983: apply postel's law to some bad encoding. + def test_encoded_word_inside_quotes(self): + self._test_get_x(parser.get_bare_quoted_string, + '"=?utf-8?Q?not_really_valid?="', + '"not really valid"', + 'not really valid', + [errors.InvalidHeaderDefect], + '') + # get_comment def test_get_comment_only(self): diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1143,6 +1143,16 @@ 'example.com', None), + 'rfc2047_atom_in_quoted_string_is_decoded': + ('"=?utf-8?q?=C3=89ric?=" ', + [errors.InvalidHeaderDefect], + '?ric ', + '?ric', + 'foo at example.com', + 'foo', + 'example.com', + None), + } # XXX: Need many more examples, and in particular some with names in diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,6 +48,9 @@ Library ------- +- Issue #16983: the new email header parsing code will now decode encoded words + that are (incorrectly) surrounded by quotes, and register a defect. + - Issue #19772: email.generator no longer mutates the message object when doing a down-transform from 8bit to 7bit CTEs. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 19:13:52 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Feb 2014 19:13:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2316983=3A_Apply_postel=27s_law_to_encoded_wor?= =?utf-8?q?ds_inside_quoted_strings=2E?= Message-ID: <3fM1jD4rYWz7LkV@mail.python.org> http://hg.python.org/cpython/rev/5f7e626730df changeset: 89056:5f7e626730df parent: 89054:2e97d3500970 parent: 89055:1dcb9d0d53a6 user: R David Murray date: Sat Feb 08 13:13:01 2014 -0500 summary: Merge: #16983: Apply postel's law to encoded words inside quoted strings. files: Lib/email/_header_value_parser.py | 7 +++++++ Lib/test/test_email/test__header_value_parser.py | 9 +++++++++ Lib/test/test_email/test_headerregistry.py | 10 ++++++++++ Misc/NEWS | 3 +++ 4 files changed, 29 insertions(+), 0 deletions(-) diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -1556,6 +1556,13 @@ while value and value[0] != '"': if value[0] in WSP: token, value = get_fws(value) + elif value[:2] == '=?': + try: + token, value = get_encoded_word(value) + bare_quoted_string.defects.append(errors.InvalidHeaderDefect( + "encoded word inside quoted string")) + except errors.HeaderParseError: + token, value = get_qcontent(value) else: token, value = get_qcontent(value) bare_quoted_string.append(token) diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -540,6 +540,15 @@ self._test_get_x(parser.get_bare_quoted_string, '""', '""', '', [], '') + # Issue 16983: apply postel's law to some bad encoding. + def test_encoded_word_inside_quotes(self): + self._test_get_x(parser.get_bare_quoted_string, + '"=?utf-8?Q?not_really_valid?="', + '"not really valid"', + 'not really valid', + [errors.InvalidHeaderDefect], + '') + # get_comment def test_get_comment_only(self): diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py --- a/Lib/test/test_email/test_headerregistry.py +++ b/Lib/test/test_email/test_headerregistry.py @@ -1155,6 +1155,16 @@ 'example.com', None), + 'rfc2047_atom_in_quoted_string_is_decoded': + ('"=?utf-8?q?=C3=89ric?=" ', + [errors.InvalidHeaderDefect], + '?ric ', + '?ric', + 'foo at example.com', + 'foo', + 'example.com', + None), + } # XXX: Need many more examples, and in particular some with names in diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,9 @@ Library ------- +- Issue #16983: the new email header parsing code will now decode encoded words + that are (incorrectly) surrounded by quotes, and register a defect. + - Issue #19772: email.generator no longer mutates the message object when doing a down-transform from 8bit to 7bit CTEs. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 20:36:25 2014 From: python-checkins at python.org (ethan.furman) Date: Sat, 8 Feb 2014 20:36:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_issue20534=3A_all_pi?= =?utf-8?q?ckle_protocols_now_supported=2E?= Message-ID: <3fM3XT6LMxz7LkD@mail.python.org> http://hg.python.org/cpython/rev/9f75f8a2cbb4 changeset: 89057:9f75f8a2cbb4 user: Ethan Furman date: Sat Feb 08 11:36:27 2014 -0800 summary: Close issue20534: all pickle protocols now supported. files: Doc/library/enum.rst | 14 +- Lib/enum.py | 28 ++- Lib/test/test_enum.py | 212 +++++++++++++++++++++++++++++- 3 files changed, 233 insertions(+), 21 deletions(-) diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -369,10 +369,10 @@ the top level of a module, since unpickling requires them to be importable from that module. -.. warning:: +.. note:: - In order to support the singleton nature of enumeration members, pickle - protocol version 2 or higher must be used. + With pickle protocol version 4 it is possible to easily pickle enums + nested in other classes. Functional API @@ -420,6 +420,14 @@ >>> Animals = Enum('Animals', 'ant bee cat dog', module=__name__) +The new pickle protocol 4 also, in some circumstances, relies on +:attr:``__qualname__`` being set to the location where pickle will be able +to find the class. For example, if the class was made available in class +SomeData in the global scope:: + + >>> Animals = Enum('Animals', 'ant bee cat dog', qualname='SomeData.Animals') + + Derived Enumerations -------------------- diff --git a/Lib/enum.py b/Lib/enum.py --- a/Lib/enum.py +++ b/Lib/enum.py @@ -31,9 +31,9 @@ def _make_class_unpicklable(cls): """Make the given class un-picklable.""" - def _break_on_call_reduce(self): + def _break_on_call_reduce(self, proto): raise TypeError('%r cannot be pickled' % self) - cls.__reduce__ = _break_on_call_reduce + cls.__reduce_ex__ = _break_on_call_reduce cls.__module__ = '' @@ -115,12 +115,13 @@ # Reverse value->name map for hashable values. enum_class._value2member_map_ = {} - # check for a __getnewargs__, and if not present sabotage + # check for a supported pickle protocols, and if not present sabotage # pickling, since it won't work anyway - if (member_type is not object and - member_type.__dict__.get('__getnewargs__') is None - ): - _make_class_unpicklable(enum_class) + if member_type is not object: + methods = ('__getnewargs_ex__', '__getnewargs__', + '__reduce_ex__', '__reduce__') + if not any(map(member_type.__dict__.get, methods)): + _make_class_unpicklable(enum_class) # instantiate them, checking for duplicates as we go # we instantiate first instead of checking for duplicates first in case @@ -166,7 +167,7 @@ # double check that repr and friends are not the mixin's or various # things break (such as pickle) - for name in ('__repr__', '__str__', '__format__', '__getnewargs__'): + for name in ('__repr__', '__str__', '__format__', '__getnewargs__', '__reduce_ex__'): class_method = getattr(enum_class, name) obj_method = getattr(member_type, name, None) enum_method = getattr(first_enum, name, None) @@ -183,7 +184,7 @@ enum_class.__new__ = Enum.__new__ return enum_class - def __call__(cls, value, names=None, *, module=None, type=None): + def __call__(cls, value, names=None, *, module=None, qualname=None, type=None): """Either returns an existing member, or creates a new enum class. This method is used both when an enum class is given a value to match @@ -202,7 +203,7 @@ if names is None: # simple value lookup return cls.__new__(cls, value) # otherwise, functional API: we're creating a new Enum type - return cls._create_(value, names, module=module, type=type) + return cls._create_(value, names, module=module, qualname=qualname, type=type) def __contains__(cls, member): return isinstance(member, cls) and member.name in cls._member_map_ @@ -273,7 +274,7 @@ raise AttributeError('Cannot reassign members.') super().__setattr__(name, value) - def _create_(cls, class_name, names=None, *, module=None, type=None): + def _create_(cls, class_name, names=None, *, module=None, qualname=None, type=None): """Convenience method to create a new Enum class. `names` can be: @@ -315,6 +316,8 @@ _make_class_unpicklable(enum_class) else: enum_class.__module__ = module + if qualname is not None: + enum_class.__qualname__ = qualname return enum_class @@ -468,6 +471,9 @@ def __hash__(self): return hash(self._name_) + def __reduce_ex__(self, proto): + return self.__class__, self.__getnewargs__() + # DynamicClassAttribute is used to provide access to the `name` and # `value` properties of enum members while keeping some measure of # protection from modification, while still allowing for an enumeration diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -52,6 +52,11 @@ except Exception as exc: Answer = exc +try: + Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition') +except Exception as exc: + Theory = exc + # for doctests try: class Fruit(Enum): @@ -61,14 +66,18 @@ except Exception: pass -def test_pickle_dump_load(assertion, source, target=None): +def test_pickle_dump_load(assertion, source, target=None, + *, protocol=(0, HIGHEST_PROTOCOL)): + start, stop = protocol if target is None: target = source - for protocol in range(2, HIGHEST_PROTOCOL+1): + for protocol in range(start, stop+1): assertion(loads(dumps(source, protocol=protocol)), target) -def test_pickle_exception(assertion, exception, obj): - for protocol in range(2, HIGHEST_PROTOCOL+1): +def test_pickle_exception(assertion, exception, obj, + *, protocol=(0, HIGHEST_PROTOCOL)): + start, stop = protocol + for protocol in range(start, stop+1): with assertion(exception): dumps(obj, protocol=protocol) @@ -101,6 +110,7 @@ class TestEnum(unittest.TestCase): + def setUp(self): class Season(Enum): SPRING = 1 @@ -540,11 +550,31 @@ test_pickle_dump_load(self.assertIs, Question.who) test_pickle_dump_load(self.assertIs, Question) + def test_enum_function_with_qualname(self): + if isinstance(Theory, Exception): + raise Theory + self.assertEqual(Theory.__qualname__, 'spanish_inquisition') + + def test_class_nested_enum_and_pickle_protocol_four(self): + # would normally just have this directly in the class namespace + class NestedEnum(Enum): + twigs = 'common' + shiny = 'rare' + + self.__class__.NestedEnum = NestedEnum + self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__ + test_pickle_exception( + self.assertRaises, PicklingError, self.NestedEnum.twigs, + protocol=(0, 3)) + test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs, + protocol=(4, HIGHEST_PROTOCOL)) + def test_exploding_pickle(self): - BadPickle = Enum('BadPickle', 'dill sweet bread-n-butter') - BadPickle.__qualname__ = 'BadPickle' # needed for pickle protocol 4 + BadPickle = Enum( + 'BadPickle', 'dill sweet bread-n-butter', module=__name__) globals()['BadPickle'] = BadPickle - enum._make_class_unpicklable(BadPickle) # will overwrite __qualname__ + # now break BadPickle to test exception raising + enum._make_class_unpicklable(BadPickle) test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill) test_pickle_exception(self.assertRaises, PicklingError, BadPickle) @@ -927,6 +957,174 @@ self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertIs, NEI.y) + def test_subclasses_with_getnewargs_ex(self): + class NamedInt(int): + __qualname__ = 'NamedInt' # needed for pickle protocol 4 + def __new__(cls, *args): + _args = args + name, *args = args + if len(args) == 0: + raise TypeError("name and value must be specified") + self = int.__new__(cls, *args) + self._intname = name + self._args = _args + return self + def __getnewargs_ex__(self): + return self._args, {} + @property + def __name__(self): + return self._intname + def __repr__(self): + # repr() is updated to include the name and type info + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) + def __str__(self): + # str() is unchanged, even if it relies on the repr() fallback + base = int + base_str = base.__str__ + if base_str.__objclass__ is object: + return base.__repr__(self) + return base_str(self) + # for simplicity, we only define one operator that + # propagates expressions + def __add__(self, other): + temp = int(self) + int( other) + if isinstance(self, NamedInt) and isinstance(other, NamedInt): + return NamedInt( + '({0} + {1})'.format(self.__name__, other.__name__), + temp ) + else: + return temp + + class NEI(NamedInt, Enum): + __qualname__ = 'NEI' # needed for pickle protocol 4 + x = ('the-x', 1) + y = ('the-y', 2) + + + self.assertIs(NEI.__new__, Enum.__new__) + self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") + globals()['NamedInt'] = NamedInt + globals()['NEI'] = NEI + NI5 = NamedInt('test', 5) + self.assertEqual(NI5, 5) + test_pickle_dump_load(self.assertEqual, NI5, 5, protocol=(4, 4)) + self.assertEqual(NEI.y.value, 2) + test_pickle_dump_load(self.assertIs, NEI.y, protocol=(4, 4)) + + def test_subclasses_with_reduce(self): + class NamedInt(int): + __qualname__ = 'NamedInt' # needed for pickle protocol 4 + def __new__(cls, *args): + _args = args + name, *args = args + if len(args) == 0: + raise TypeError("name and value must be specified") + self = int.__new__(cls, *args) + self._intname = name + self._args = _args + return self + def __reduce__(self): + return self.__class__, self._args + @property + def __name__(self): + return self._intname + def __repr__(self): + # repr() is updated to include the name and type info + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) + def __str__(self): + # str() is unchanged, even if it relies on the repr() fallback + base = int + base_str = base.__str__ + if base_str.__objclass__ is object: + return base.__repr__(self) + return base_str(self) + # for simplicity, we only define one operator that + # propagates expressions + def __add__(self, other): + temp = int(self) + int( other) + if isinstance(self, NamedInt) and isinstance(other, NamedInt): + return NamedInt( + '({0} + {1})'.format(self.__name__, other.__name__), + temp ) + else: + return temp + + class NEI(NamedInt, Enum): + __qualname__ = 'NEI' # needed for pickle protocol 4 + x = ('the-x', 1) + y = ('the-y', 2) + + + self.assertIs(NEI.__new__, Enum.__new__) + self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") + globals()['NamedInt'] = NamedInt + globals()['NEI'] = NEI + NI5 = NamedInt('test', 5) + self.assertEqual(NI5, 5) + test_pickle_dump_load(self.assertEqual, NI5, 5) + self.assertEqual(NEI.y.value, 2) + test_pickle_dump_load(self.assertIs, NEI.y) + + def test_subclasses_with_reduce_ex(self): + class NamedInt(int): + __qualname__ = 'NamedInt' # needed for pickle protocol 4 + def __new__(cls, *args): + _args = args + name, *args = args + if len(args) == 0: + raise TypeError("name and value must be specified") + self = int.__new__(cls, *args) + self._intname = name + self._args = _args + return self + def __reduce_ex__(self, proto): + return self.__class__, self._args + @property + def __name__(self): + return self._intname + def __repr__(self): + # repr() is updated to include the name and type info + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) + def __str__(self): + # str() is unchanged, even if it relies on the repr() fallback + base = int + base_str = base.__str__ + if base_str.__objclass__ is object: + return base.__repr__(self) + return base_str(self) + # for simplicity, we only define one operator that + # propagates expressions + def __add__(self, other): + temp = int(self) + int( other) + if isinstance(self, NamedInt) and isinstance(other, NamedInt): + return NamedInt( + '({0} + {1})'.format(self.__name__, other.__name__), + temp ) + else: + return temp + + class NEI(NamedInt, Enum): + __qualname__ = 'NEI' # needed for pickle protocol 4 + x = ('the-x', 1) + y = ('the-y', 2) + + + self.assertIs(NEI.__new__, Enum.__new__) + self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") + globals()['NamedInt'] = NamedInt + globals()['NEI'] = NEI + NI5 = NamedInt('test', 5) + self.assertEqual(NI5, 5) + test_pickle_dump_load(self.assertEqual, NI5, 5) + self.assertEqual(NEI.y.value, 2) + test_pickle_dump_load(self.assertIs, NEI.y) + def test_subclasses_without_getnewargs(self): class NamedInt(int): __qualname__ = 'NamedInt' -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 22:55:35 2014 From: python-checkins at python.org (charles-francois.natali) Date: Sat, 8 Feb 2014 22:55:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwMDY1?= =?utf-8?q?=3A_socketmodule=3A_Fix_build_error_when_AF=5FCAN_is_defined_wi?= =?utf-8?q?thout_the?= Message-ID: <3fM6d357VWz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/b1ff233d3ab1 changeset: 89058:b1ff233d3ab1 branch: 3.3 parent: 89055:1dcb9d0d53a6 user: Charles-Fran?ois Natali date: Sat Feb 08 22:54:11 2014 +0100 summary: Issue #20065: socketmodule: Fix build error when AF_CAN is defined without the proper CAN headers. files: Modules/socketmodule.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1226,7 +1226,7 @@ } #endif -#ifdef AF_CAN +#ifdef HAVE_LINUX_CAN_H case AF_CAN: { struct sockaddr_can *a = (struct sockaddr_can *)addr; @@ -1654,7 +1654,7 @@ } #endif -#ifdef AF_CAN +#ifdef HAVE_LINUX_CAN_H case AF_CAN: switch (s->sock_proto) { case CAN_RAW: @@ -1859,7 +1859,7 @@ } #endif -#ifdef AF_CAN +#ifdef HAVE_LINUX_CAN_H case AF_CAN: { *len_ret = sizeof (struct sockaddr_can); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 22:55:36 2014 From: python-checkins at python.org (charles-francois.natali) Date: Sat, 8 Feb 2014 22:55:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320065=3A_socketmodule=3A_Fix_build_error_when_A?= =?utf-8?q?F=5FCAN_is_defined_without_the?= Message-ID: <3fM6d46WRnz7LjN@mail.python.org> http://hg.python.org/cpython/rev/39a60d62d2a6 changeset: 89059:39a60d62d2a6 parent: 89056:5f7e626730df parent: 89058:b1ff233d3ab1 user: Charles-Fran?ois Natali date: Sat Feb 08 22:54:48 2014 +0100 summary: Issue #20065: socketmodule: Fix build error when AF_CAN is defined without the proper CAN headers. files: Modules/socketmodule.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1165,7 +1165,7 @@ } #endif -#ifdef AF_CAN +#ifdef HAVE_LINUX_CAN_H case AF_CAN: { struct sockaddr_can *a = (struct sockaddr_can *)addr; @@ -1589,7 +1589,7 @@ } #endif -#ifdef AF_CAN +#ifdef HAVE_LINUX_CAN_H case AF_CAN: switch (s->sock_proto) { case CAN_RAW: @@ -1796,7 +1796,7 @@ } #endif -#ifdef AF_CAN +#ifdef HAVE_LINUX_CAN_H case AF_CAN: { *len_ret = sizeof (struct sockaddr_can); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 22:55:38 2014 From: python-checkins at python.org (charles-francois.natali) Date: Sat, 8 Feb 2014 22:55:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?b?KTogTWVyZ2Uu?= Message-ID: <3fM6d62kXwz7Lk9@mail.python.org> http://hg.python.org/cpython/rev/68c40567e8f8 changeset: 89060:68c40567e8f8 parent: 89059:39a60d62d2a6 parent: 89057:9f75f8a2cbb4 user: Charles-Fran?ois Natali date: Sat Feb 08 22:55:13 2014 +0100 summary: Merge. files: Doc/library/enum.rst | 14 +- Lib/enum.py | 28 ++- Lib/test/test_enum.py | 212 +++++++++++++++++++++++++++++- 3 files changed, 233 insertions(+), 21 deletions(-) diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -369,10 +369,10 @@ the top level of a module, since unpickling requires them to be importable from that module. -.. warning:: +.. note:: - In order to support the singleton nature of enumeration members, pickle - protocol version 2 or higher must be used. + With pickle protocol version 4 it is possible to easily pickle enums + nested in other classes. Functional API @@ -420,6 +420,14 @@ >>> Animals = Enum('Animals', 'ant bee cat dog', module=__name__) +The new pickle protocol 4 also, in some circumstances, relies on +:attr:``__qualname__`` being set to the location where pickle will be able +to find the class. For example, if the class was made available in class +SomeData in the global scope:: + + >>> Animals = Enum('Animals', 'ant bee cat dog', qualname='SomeData.Animals') + + Derived Enumerations -------------------- diff --git a/Lib/enum.py b/Lib/enum.py --- a/Lib/enum.py +++ b/Lib/enum.py @@ -31,9 +31,9 @@ def _make_class_unpicklable(cls): """Make the given class un-picklable.""" - def _break_on_call_reduce(self): + def _break_on_call_reduce(self, proto): raise TypeError('%r cannot be pickled' % self) - cls.__reduce__ = _break_on_call_reduce + cls.__reduce_ex__ = _break_on_call_reduce cls.__module__ = '' @@ -115,12 +115,13 @@ # Reverse value->name map for hashable values. enum_class._value2member_map_ = {} - # check for a __getnewargs__, and if not present sabotage + # check for a supported pickle protocols, and if not present sabotage # pickling, since it won't work anyway - if (member_type is not object and - member_type.__dict__.get('__getnewargs__') is None - ): - _make_class_unpicklable(enum_class) + if member_type is not object: + methods = ('__getnewargs_ex__', '__getnewargs__', + '__reduce_ex__', '__reduce__') + if not any(map(member_type.__dict__.get, methods)): + _make_class_unpicklable(enum_class) # instantiate them, checking for duplicates as we go # we instantiate first instead of checking for duplicates first in case @@ -166,7 +167,7 @@ # double check that repr and friends are not the mixin's or various # things break (such as pickle) - for name in ('__repr__', '__str__', '__format__', '__getnewargs__'): + for name in ('__repr__', '__str__', '__format__', '__getnewargs__', '__reduce_ex__'): class_method = getattr(enum_class, name) obj_method = getattr(member_type, name, None) enum_method = getattr(first_enum, name, None) @@ -183,7 +184,7 @@ enum_class.__new__ = Enum.__new__ return enum_class - def __call__(cls, value, names=None, *, module=None, type=None): + def __call__(cls, value, names=None, *, module=None, qualname=None, type=None): """Either returns an existing member, or creates a new enum class. This method is used both when an enum class is given a value to match @@ -202,7 +203,7 @@ if names is None: # simple value lookup return cls.__new__(cls, value) # otherwise, functional API: we're creating a new Enum type - return cls._create_(value, names, module=module, type=type) + return cls._create_(value, names, module=module, qualname=qualname, type=type) def __contains__(cls, member): return isinstance(member, cls) and member.name in cls._member_map_ @@ -273,7 +274,7 @@ raise AttributeError('Cannot reassign members.') super().__setattr__(name, value) - def _create_(cls, class_name, names=None, *, module=None, type=None): + def _create_(cls, class_name, names=None, *, module=None, qualname=None, type=None): """Convenience method to create a new Enum class. `names` can be: @@ -315,6 +316,8 @@ _make_class_unpicklable(enum_class) else: enum_class.__module__ = module + if qualname is not None: + enum_class.__qualname__ = qualname return enum_class @@ -468,6 +471,9 @@ def __hash__(self): return hash(self._name_) + def __reduce_ex__(self, proto): + return self.__class__, self.__getnewargs__() + # DynamicClassAttribute is used to provide access to the `name` and # `value` properties of enum members while keeping some measure of # protection from modification, while still allowing for an enumeration diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -52,6 +52,11 @@ except Exception as exc: Answer = exc +try: + Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition') +except Exception as exc: + Theory = exc + # for doctests try: class Fruit(Enum): @@ -61,14 +66,18 @@ except Exception: pass -def test_pickle_dump_load(assertion, source, target=None): +def test_pickle_dump_load(assertion, source, target=None, + *, protocol=(0, HIGHEST_PROTOCOL)): + start, stop = protocol if target is None: target = source - for protocol in range(2, HIGHEST_PROTOCOL+1): + for protocol in range(start, stop+1): assertion(loads(dumps(source, protocol=protocol)), target) -def test_pickle_exception(assertion, exception, obj): - for protocol in range(2, HIGHEST_PROTOCOL+1): +def test_pickle_exception(assertion, exception, obj, + *, protocol=(0, HIGHEST_PROTOCOL)): + start, stop = protocol + for protocol in range(start, stop+1): with assertion(exception): dumps(obj, protocol=protocol) @@ -101,6 +110,7 @@ class TestEnum(unittest.TestCase): + def setUp(self): class Season(Enum): SPRING = 1 @@ -540,11 +550,31 @@ test_pickle_dump_load(self.assertIs, Question.who) test_pickle_dump_load(self.assertIs, Question) + def test_enum_function_with_qualname(self): + if isinstance(Theory, Exception): + raise Theory + self.assertEqual(Theory.__qualname__, 'spanish_inquisition') + + def test_class_nested_enum_and_pickle_protocol_four(self): + # would normally just have this directly in the class namespace + class NestedEnum(Enum): + twigs = 'common' + shiny = 'rare' + + self.__class__.NestedEnum = NestedEnum + self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__ + test_pickle_exception( + self.assertRaises, PicklingError, self.NestedEnum.twigs, + protocol=(0, 3)) + test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs, + protocol=(4, HIGHEST_PROTOCOL)) + def test_exploding_pickle(self): - BadPickle = Enum('BadPickle', 'dill sweet bread-n-butter') - BadPickle.__qualname__ = 'BadPickle' # needed for pickle protocol 4 + BadPickle = Enum( + 'BadPickle', 'dill sweet bread-n-butter', module=__name__) globals()['BadPickle'] = BadPickle - enum._make_class_unpicklable(BadPickle) # will overwrite __qualname__ + # now break BadPickle to test exception raising + enum._make_class_unpicklable(BadPickle) test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill) test_pickle_exception(self.assertRaises, PicklingError, BadPickle) @@ -927,6 +957,174 @@ self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertIs, NEI.y) + def test_subclasses_with_getnewargs_ex(self): + class NamedInt(int): + __qualname__ = 'NamedInt' # needed for pickle protocol 4 + def __new__(cls, *args): + _args = args + name, *args = args + if len(args) == 0: + raise TypeError("name and value must be specified") + self = int.__new__(cls, *args) + self._intname = name + self._args = _args + return self + def __getnewargs_ex__(self): + return self._args, {} + @property + def __name__(self): + return self._intname + def __repr__(self): + # repr() is updated to include the name and type info + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) + def __str__(self): + # str() is unchanged, even if it relies on the repr() fallback + base = int + base_str = base.__str__ + if base_str.__objclass__ is object: + return base.__repr__(self) + return base_str(self) + # for simplicity, we only define one operator that + # propagates expressions + def __add__(self, other): + temp = int(self) + int( other) + if isinstance(self, NamedInt) and isinstance(other, NamedInt): + return NamedInt( + '({0} + {1})'.format(self.__name__, other.__name__), + temp ) + else: + return temp + + class NEI(NamedInt, Enum): + __qualname__ = 'NEI' # needed for pickle protocol 4 + x = ('the-x', 1) + y = ('the-y', 2) + + + self.assertIs(NEI.__new__, Enum.__new__) + self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") + globals()['NamedInt'] = NamedInt + globals()['NEI'] = NEI + NI5 = NamedInt('test', 5) + self.assertEqual(NI5, 5) + test_pickle_dump_load(self.assertEqual, NI5, 5, protocol=(4, 4)) + self.assertEqual(NEI.y.value, 2) + test_pickle_dump_load(self.assertIs, NEI.y, protocol=(4, 4)) + + def test_subclasses_with_reduce(self): + class NamedInt(int): + __qualname__ = 'NamedInt' # needed for pickle protocol 4 + def __new__(cls, *args): + _args = args + name, *args = args + if len(args) == 0: + raise TypeError("name and value must be specified") + self = int.__new__(cls, *args) + self._intname = name + self._args = _args + return self + def __reduce__(self): + return self.__class__, self._args + @property + def __name__(self): + return self._intname + def __repr__(self): + # repr() is updated to include the name and type info + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) + def __str__(self): + # str() is unchanged, even if it relies on the repr() fallback + base = int + base_str = base.__str__ + if base_str.__objclass__ is object: + return base.__repr__(self) + return base_str(self) + # for simplicity, we only define one operator that + # propagates expressions + def __add__(self, other): + temp = int(self) + int( other) + if isinstance(self, NamedInt) and isinstance(other, NamedInt): + return NamedInt( + '({0} + {1})'.format(self.__name__, other.__name__), + temp ) + else: + return temp + + class NEI(NamedInt, Enum): + __qualname__ = 'NEI' # needed for pickle protocol 4 + x = ('the-x', 1) + y = ('the-y', 2) + + + self.assertIs(NEI.__new__, Enum.__new__) + self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") + globals()['NamedInt'] = NamedInt + globals()['NEI'] = NEI + NI5 = NamedInt('test', 5) + self.assertEqual(NI5, 5) + test_pickle_dump_load(self.assertEqual, NI5, 5) + self.assertEqual(NEI.y.value, 2) + test_pickle_dump_load(self.assertIs, NEI.y) + + def test_subclasses_with_reduce_ex(self): + class NamedInt(int): + __qualname__ = 'NamedInt' # needed for pickle protocol 4 + def __new__(cls, *args): + _args = args + name, *args = args + if len(args) == 0: + raise TypeError("name and value must be specified") + self = int.__new__(cls, *args) + self._intname = name + self._args = _args + return self + def __reduce_ex__(self, proto): + return self.__class__, self._args + @property + def __name__(self): + return self._intname + def __repr__(self): + # repr() is updated to include the name and type info + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) + def __str__(self): + # str() is unchanged, even if it relies on the repr() fallback + base = int + base_str = base.__str__ + if base_str.__objclass__ is object: + return base.__repr__(self) + return base_str(self) + # for simplicity, we only define one operator that + # propagates expressions + def __add__(self, other): + temp = int(self) + int( other) + if isinstance(self, NamedInt) and isinstance(other, NamedInt): + return NamedInt( + '({0} + {1})'.format(self.__name__, other.__name__), + temp ) + else: + return temp + + class NEI(NamedInt, Enum): + __qualname__ = 'NEI' # needed for pickle protocol 4 + x = ('the-x', 1) + y = ('the-y', 2) + + + self.assertIs(NEI.__new__, Enum.__new__) + self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") + globals()['NamedInt'] = NamedInt + globals()['NEI'] = NEI + NI5 = NamedInt('test', 5) + self.assertEqual(NI5, 5) + test_pickle_dump_load(self.assertEqual, NI5, 5) + self.assertEqual(NEI.y.value, 2) + test_pickle_dump_load(self.assertIs, NEI.y) + def test_subclasses_without_getnewargs(self): class NamedInt(int): __qualname__ = 'NamedInt' -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 23:09:18 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 8 Feb 2014 23:09:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTQw?= =?utf-8?q?=3A_Fix_a_performance_regression_=28vs=2E_Python_3=2E2=29_when_?= =?utf-8?q?layering_a?= Message-ID: <3fM6wt0DwHz7Ljg@mail.python.org> http://hg.python.org/cpython/rev/4816ab0477d2 changeset: 89061:4816ab0477d2 branch: 3.3 parent: 89058:b1ff233d3ab1 user: Antoine Pitrou date: Sat Feb 08 23:03:56 2014 +0100 summary: Issue #20540: Fix a performance regression (vs. Python 3.2) when layering a multiprocessing Connection over a TCP socket. For small payloads, Nagle's algorithm would introduce idle delays before the entire transmission of a message. files: Lib/multiprocessing/connection.py | 22 +++++++++++++----- Misc/NEWS | 5 ++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -395,13 +395,23 @@ return buf def _send_bytes(self, buf): + n = len(buf) # For wire compatibility with 3.2 and lower - n = len(buf) - self._send(struct.pack("!i", n)) - # The condition is necessary to avoid "broken pipe" errors - # when sending a 0-length buffer if the other end closed the pipe. - if n > 0: - self._send(buf) + header = struct.pack("!i", n) + if n > 16384: + # The payload is large so Nagle's algorithm won't be triggered + # and we'd better avoid the cost of concatenation. + chunks = [header, buf] + elif n > 0: + # Issue #?20540: concatenate before sending, to avoid delays due + # to Nagle's algorithm on a TCP socket. + chunks = [header + buf] + else: + # This code path is necessary to avoid "broken pipe" errors + # when sending a 0-length buffer if the other end closed the pipe. + chunks = [header] + for chunk in chunks: + self._send(chunk) def _recv_bytes(self, maxsize=None): buf = self._recv(4) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,6 +48,11 @@ Library ------- +- Issue #20540: Fix a performance regression (vs. Python 3.2) when layering + a multiprocessing Connection over a TCP socket. For small payloads, Nagle's + algorithm would introduce idle delays before the entire transmission of a + message. + - Issue #16983: the new email header parsing code will now decode encoded words that are (incorrectly) surrounded by quotes, and register a defect. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 23:09:19 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 8 Feb 2014 23:09:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320540=3A_Fix_a_performance_regression_=28vs=2E_?= =?utf-8?q?Python_3=2E2=29_when_layering_a?= Message-ID: <3fM6wv1l40z7Ljg@mail.python.org> http://hg.python.org/cpython/rev/125c24f47f3c changeset: 89062:125c24f47f3c parent: 89060:68c40567e8f8 parent: 89061:4816ab0477d2 user: Antoine Pitrou date: Sat Feb 08 23:05:52 2014 +0100 summary: Issue #20540: Fix a performance regression (vs. Python 3.2) when layering a multiprocessing Connection over a TCP socket. For small payloads, Nagle's algorithm would introduce idle delays before the entire transmission of a message. files: Lib/multiprocessing/connection.py | 22 +++++++++++++----- Misc/NEWS | 5 ++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -395,13 +395,23 @@ return buf def _send_bytes(self, buf): + n = len(buf) # For wire compatibility with 3.2 and lower - n = len(buf) - self._send(struct.pack("!i", n)) - # The condition is necessary to avoid "broken pipe" errors - # when sending a 0-length buffer if the other end closed the pipe. - if n > 0: - self._send(buf) + header = struct.pack("!i", n) + if n > 16384: + # The payload is large so Nagle's algorithm won't be triggered + # and we'd better avoid the cost of concatenation. + chunks = [header, buf] + elif n > 0: + # Issue #?20540: concatenate before sending, to avoid delays due + # to Nagle's algorithm on a TCP socket. + chunks = [header + buf] + else: + # This code path is necessary to avoid "broken pipe" errors + # when sending a 0-length buffer if the other end closed the pipe. + chunks = [header] + for chunk in chunks: + self._send(chunk) def _recv_bytes(self, maxsize=None): buf = self._recv(4) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,11 @@ Library ------- +- Issue #20540: Fix a performance regression (vs. Python 3.2) when layering + a multiprocessing Connection over a TCP socket. For small payloads, Nagle's + algorithm would introduce idle delays before the entire transmission of a + message. + - Issue #16983: the new email header parsing code will now decode encoded words that are (incorrectly) surrounded by quotes, and register a defect. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 23:23:27 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 8 Feb 2014 23:23:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_sort_method?= =?utf-8?q?s?= Message-ID: <3fM7FC3bc0z7LjQ@mail.python.org> http://hg.python.org/cpython/rev/6c07690d9f3a changeset: 89063:6c07690d9f3a user: Victor Stinner date: Sat Feb 08 22:50:07 2014 +0100 summary: asyncio doc: sort methods files: Doc/library/asyncio-stream.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -123,6 +123,11 @@ Transport. + .. method:: can_write_eof() + + Return :const:`True` if the transport supports :meth:`write_eof`, + :const:`False` if not. See :meth:`WriteTransport.can_write_eof`. + .. method:: close() Close the transport: see :meth:`BaseTransport.close`. @@ -158,11 +163,6 @@ Write a list (or any iterable) of data bytes to the transport: see :meth:`WriteTransport.writelines`. - .. method:: can_write_eof() - - Return :const:`True` if the transport supports :meth:`write_eof`, - :const:`False` if not. See :meth:`WriteTransport.can_write_eof`. - .. method:: write_eof() Close the write end of the transport after flushing buffered data: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 23:23:28 2014 From: python-checkins at python.org (victor.stinner) Date: Sat, 8 Feb 2014 23:23:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_document_mi?= =?utf-8?q?ssing_event_loop_methods?= Message-ID: <3fM7FD5KbGz7Lks@mail.python.org> http://hg.python.org/cpython/rev/a4030dd01456 changeset: 89064:a4030dd01456 user: Victor Stinner date: Sat Feb 08 23:22:58 2014 +0100 summary: asyncio doc: document missing event loop methods files: Doc/library/asyncio-eventloop.rst | 90 ++++++++++++++++++- 1 files changed, 86 insertions(+), 4 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -272,16 +272,98 @@ -Resolve name ------------- +Watch file descriptors +---------------------- + +.. method:: BaseEventLoop.add_reader(fd, callback, \*args) + + Start watching the file descriptor for read availability and then call the + *callback* with specified arguments. + +.. method:: BaseEventLoop.remove_reader(fd) + + Stop watching the file descriptor for read availability. + +.. method:: BaseEventLoop.add_writer(fd, callback, \*args) + + Start watching the file descriptor for write availability and then call the + *callback* with specified arguments. + +.. method:: BaseEventLoop.remove_writer(fd) + + Stop watching the file descriptor for write availability. + + +Low-level socket operations +--------------------------- + +.. method:: BaseEventLoop.sock_recv(sock, nbytes) + + 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 returns a :ref:`coroutine object `. + + .. seealso:: + + The :meth:`socket.socket.recv` method. + +.. method:: BaseEventLoop.sock_sendall(sock, data) + + Send data to the socket. The socket must be connected to a remote socket. + This method continues to send data from *data* until either all data has + been sent or an 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 sent. + + This method returns a :ref:`coroutine object `. + + .. seealso:: + + The :meth:`socket.socket.sendall` method. + +.. method:: BaseEventLoop.sock_connect(sock, address) + + Connect to a remote socket at *address*. + + This method returns a :ref:`coroutine object `. + + .. seealso:: + + The :meth:`BaseEventLoop.create_connection` method, the + :func:`open_connection` function and the :meth:`socket.socket.connect` + method. + + +.. method:: BaseEventLoop.sock_accept(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 returns a :ref:`coroutine object `. + + .. seealso:: + + The :meth:`BaseEventLoop.create_server` method, the :func:`start_server` + function and the :meth:`socket.socket.accept` method. + + +Resolve host name +----------------- .. method:: BaseEventLoop.getaddrinfo(host, port, \*, family=0, type=0, proto=0, flags=0) - XXX + Similar to the :meth:`socket.getaddrinfo` function, but return a + :ref:`coroutine object `. .. method:: BaseEventLoop.getnameinfo(sockaddr, flags=0) - XXX + Similar to the :meth:`socket.getnameinfo` function, but return a + :ref:`coroutine object `. Running subprocesses -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 23:28:53 2014 From: python-checkins at python.org (senthil.kumaran) Date: Sat, 8 Feb 2014 23:28:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Include_the_me?= =?utf-8?q?ntion_of_ResourceWarning_being_displayed_by_default_by_the_test?= Message-ID: <3fM7MT1DT9z7Ljg@mail.python.org> http://hg.python.org/cpython/rev/a8a6dc7f478b changeset: 89065:a8a6dc7f478b branch: 3.3 parent: 89061:4816ab0477d2 user: Senthil Kumaran date: Sat Feb 08 14:28:03 2014 -0800 summary: Include the mention of ResourceWarning being displayed by default by the test runner. Addressing #issue 20529 files: Doc/library/unittest.rst | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1754,13 +1754,14 @@ applications which run test suites should provide alternate implementations. By default this runner shows :exc:`DeprecationWarning`, - :exc:`PendingDeprecationWarning`, and :exc:`ImportWarning` even if they are - :ref:`ignored by default `. Deprecation warnings caused by - :ref:`deprecated unittest methods ` are also - special-cased and, when the warning filters are ``'default'`` or ``'always'``, - they will appear only once per-module, in order to avoid too many warning - messages. This behavior can be overridden using the :option:`-Wd` or - :option:`-Wa` options and leaving *warnings* to ``None``. + :exc:`PendingDeprecationWarning`, :exc:`ResourceWarning` and + :exc:`ImportWarning` even if they are :ref:`ignored by default `. Deprecation warnings caused by :ref:`deprecated unittest methods + ` are also special-cased and, when the warning filters + are ``'default'`` or ``'always'``, they will appear only once per-module, in + order to avoid too many warning messages. This behavior can be overridden + using the :option:`-Wd` or :option:`-Wa` options and leaving *warnings* to + ``None``. .. versionchanged:: 3.2 Added the ``warnings`` argument. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 23:28:54 2014 From: python-checkins at python.org (senthil.kumaran) Date: Sat, 8 Feb 2014 23:28:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge_from_3=2E3?= Message-ID: <3fM7MV3QGPz7LkY@mail.python.org> http://hg.python.org/cpython/rev/7fc1e8095fb8 changeset: 89066:7fc1e8095fb8 parent: 89064:a4030dd01456 parent: 89065:a8a6dc7f478b user: Senthil Kumaran date: Sat Feb 08 14:28:44 2014 -0800 summary: merge from 3.3 Include the mention of ResourceWarning being displayed by default by the test runner. Addressing #issue 20529 files: Doc/library/unittest.rst | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1916,13 +1916,14 @@ applications which run test suites should provide alternate implementations. By default this runner shows :exc:`DeprecationWarning`, - :exc:`PendingDeprecationWarning`, and :exc:`ImportWarning` even if they are - :ref:`ignored by default `. Deprecation warnings caused by - :ref:`deprecated unittest methods ` are also - special-cased and, when the warning filters are ``'default'`` or ``'always'``, - they will appear only once per-module, in order to avoid too many warning - messages. This behavior can be overridden using the :option:`-Wd` or - :option:`-Wa` options and leaving *warnings* to ``None``. + :exc:`PendingDeprecationWarning`, :exc:`ResourceWarning` and + :exc:`ImportWarning` even if they are :ref:`ignored by default `. Deprecation warnings caused by :ref:`deprecated unittest methods + ` are also special-cased and, when the warning filters + are ``'default'`` or ``'always'``, they will appear only once per-module, in + order to avoid too many warning messages. This behavior can be overridden + using the :option:`-Wd` or :option:`-Wa` options and leaving *warnings* to + ``None``. .. versionchanged:: 3.2 Added the ``warnings`` argument. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 23:56:38 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Feb 2014 23:56:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE0OTgzOiBhbHdh?= =?utf-8?q?ys_add_a_line_end_after_a_MIME_boundary_marker=2E?= Message-ID: <3fM7zV2Fj5z7Ljd@mail.python.org> http://hg.python.org/cpython/rev/d579866d6419 changeset: 89067:d579866d6419 branch: 2.7 parent: 89052:d4f9efd4be7d user: R David Murray date: Sat Feb 08 17:54:12 2014 -0500 summary: #14983: always add a line end after a MIME boundary marker. This is more RFC compliant (see issue) and fixes a problem with signature verifiers rejecting the part when signed. There is some amount of backward compatibility concern here since it changes the output, but the RFC issue coupled with fixing the problem with signature verifiers seems worth the small risk of breaking code that depends on the current incorrect output. files: Lib/email/generator.py | 3 +-- Lib/email/test/data/msg_02.txt | 1 + Lib/email/test/test_email.py | 15 ++++++++++----- Lib/email/test/test_email_renamed.py | 15 ++++++++++----- Misc/NEWS | 4 ++++ 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -231,9 +231,8 @@ # body-part self._fp.write(body_part) # close-delimiter transport-padding - self._fp.write('\n--' + boundary + '--') + self._fp.write('\n--' + boundary + '--' + NL) if msg.epilogue is not None: - print >> self._fp if self._mangle_from_: epilogue = fcre.sub('>From ', msg.epilogue) else: diff --git a/Lib/email/test/data/msg_02.txt b/Lib/email/test/data/msg_02.txt --- a/Lib/email/test/data/msg_02.txt +++ b/Lib/email/test/data/msg_02.txt @@ -119,6 +119,7 @@ --__--__---- + --192.168.1.2.889.32614.987812255.500.21814 Content-type: text/plain; charset=us-ascii Content-description: Digest Footer diff --git a/Lib/email/test/test_email.py b/Lib/email/test/test_email.py --- a/Lib/email/test/test_email.py +++ b/Lib/email/test/test_email.py @@ -1206,7 +1206,8 @@ --BOUNDARY ---BOUNDARY--''') +--BOUNDARY-- +''') def test_no_parts_in_a_multipart_with_empty_epilogue(self): outer = MIMEBase('multipart', 'mixed') @@ -1251,7 +1252,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_empty_preamble(self): eq = self.ndiffAssertEqual @@ -1277,7 +1279,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_none_preamble(self): @@ -1303,7 +1306,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_none_epilogue(self): @@ -1329,7 +1333,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_empty_epilogue(self): diff --git a/Lib/email/test/test_email_renamed.py b/Lib/email/test/test_email_renamed.py --- a/Lib/email/test/test_email_renamed.py +++ b/Lib/email/test/test_email_renamed.py @@ -1146,7 +1146,8 @@ --BOUNDARY ---BOUNDARY--''') +--BOUNDARY-- +''') def test_no_parts_in_a_multipart_with_empty_epilogue(self): outer = MIMEBase('multipart', 'mixed') @@ -1191,7 +1192,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_empty_preamble(self): eq = self.ndiffAssertEqual @@ -1217,7 +1219,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_none_preamble(self): @@ -1243,7 +1246,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_none_epilogue(self): @@ -1269,7 +1273,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_empty_epilogue(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,10 @@ Library ------- +- Issue #14983: email.generator now always adds a line end after each MIME + boundary marker, instead of doing so only when there is an epilogue. This + fixes an RFC compliance bug and solves an issue with signed MIME parts. + - Issue #20013: Some imap servers disconnect if the current mailbox is deleted, and imaplib did not handle that case gracefully. Now it handles the 'bye' correctly. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 23:56:39 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Feb 2014 23:56:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE0OTgzOiBhbHdh?= =?utf-8?q?ys_add_a_line_end_after_a_MIME_boundary_marker=2E?= Message-ID: <3fM7zW42sPz7Ljm@mail.python.org> http://hg.python.org/cpython/rev/c2538789c8cf changeset: 89068:c2538789c8cf branch: 3.3 parent: 89065:a8a6dc7f478b user: R David Murray date: Sat Feb 08 17:54:56 2014 -0500 summary: #14983: always add a line end after a MIME boundary marker. This is more RFC compliant (see issue) and fixes a problem with signature verifiers rejecting the part when signed. There is some amount of backward compatibility concern here since it changes the output, but the RFC issue coupled with fixing the problem with signature verifiers seems worth the small risk of breaking code that depends on the current incorrect output. files: Lib/email/generator.py | 3 +-- Lib/test/test_email/data/msg_02.txt | 1 + Lib/test/test_email/test_email.py | 15 ++++++++++----- Misc/NEWS | 4 ++++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -299,9 +299,8 @@ # body-part self._fp.write(body_part) # close-delimiter transport-padding - self.write(self._NL + '--' + boundary + '--') + self.write(self._NL + '--' + boundary + '--' + self._NL) if msg.epilogue is not None: - self.write(self._NL) if self._mangle_from_: epilogue = fcre.sub('>From ', msg.epilogue) else: diff --git a/Lib/test/test_email/data/msg_02.txt b/Lib/test/test_email/data/msg_02.txt --- a/Lib/test/test_email/data/msg_02.txt +++ b/Lib/test/test_email/data/msg_02.txt @@ -119,6 +119,7 @@ --__--__---- + --192.168.1.2.889.32614.987812255.500.21814 Content-type: text/plain; charset=us-ascii Content-description: Digest Footer diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -1711,7 +1711,8 @@ --BOUNDARY ---BOUNDARY--''') +--BOUNDARY-- +''') def test_no_parts_in_a_multipart_with_empty_epilogue(self): outer = MIMEBase('multipart', 'mixed') @@ -1756,7 +1757,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_empty_preamble(self): eq = self.ndiffAssertEqual @@ -1782,7 +1784,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_none_preamble(self): @@ -1808,7 +1811,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_none_epilogue(self): @@ -1834,7 +1838,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_empty_epilogue(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -48,6 +48,10 @@ Library ------- +- Issue #14983: email.generator now always adds a line end after each MIME + boundary marker, instead of doing so only when there is an epilogue. This + fixes an RFC compliance bug and solves an issue with signed MIME parts. + - Issue #20540: Fix a performance regression (vs. Python 3.2) when layering a multiprocessing Connection over a TCP socket. For small payloads, Nagle's algorithm would introduce idle delays before the entire transmission of a -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 8 23:56:40 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Feb 2014 23:56:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2314983=3A_always_add_a_line_end_after_a_MIME_?= =?utf-8?q?boundary_marker=2E?= Message-ID: <3fM7zX6BMRz7Lkn@mail.python.org> http://hg.python.org/cpython/rev/7486c45eb53f changeset: 89069:7486c45eb53f parent: 89066:7fc1e8095fb8 parent: 89068:c2538789c8cf user: R David Murray date: Sat Feb 08 17:56:17 2014 -0500 summary: Merge: #14983: always add a line end after a MIME boundary marker. files: Lib/email/generator.py | 3 +-- Lib/test/test_email/data/msg_02.txt | 1 + Lib/test/test_email/test_email.py | 15 ++++++++++----- Misc/NEWS | 4 ++++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Lib/email/generator.py b/Lib/email/generator.py --- a/Lib/email/generator.py +++ b/Lib/email/generator.py @@ -299,9 +299,8 @@ # body-part self._fp.write(body_part) # close-delimiter transport-padding - self.write(self._NL + '--' + boundary + '--') + self.write(self._NL + '--' + boundary + '--' + self._NL) if msg.epilogue is not None: - self.write(self._NL) if self._mangle_from_: epilogue = fcre.sub('>From ', msg.epilogue) else: diff --git a/Lib/test/test_email/data/msg_02.txt b/Lib/test/test_email/data/msg_02.txt --- a/Lib/test/test_email/data/msg_02.txt +++ b/Lib/test/test_email/data/msg_02.txt @@ -119,6 +119,7 @@ --__--__---- + --192.168.1.2.889.32614.987812255.500.21814 Content-type: text/plain; charset=us-ascii Content-description: Digest Footer diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py --- a/Lib/test/test_email/test_email.py +++ b/Lib/test/test_email/test_email.py @@ -1745,7 +1745,8 @@ --BOUNDARY ---BOUNDARY--''') +--BOUNDARY-- +''') def test_no_parts_in_a_multipart_with_empty_epilogue(self): outer = MIMEBase('multipart', 'mixed') @@ -1790,7 +1791,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_empty_preamble(self): eq = self.ndiffAssertEqual @@ -1816,7 +1818,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_none_preamble(self): @@ -1842,7 +1845,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_none_epilogue(self): @@ -1868,7 +1872,8 @@ Content-Transfer-Encoding: 7bit hello world ---BOUNDARY--''') +--BOUNDARY-- +''') def test_seq_parts_in_a_multipart_with_empty_epilogue(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,10 @@ Library ------- +- Issue #14983: email.generator now always adds a line end after each MIME + boundary marker, instead of doing so only when there is an epilogue. This + fixes an RFC compliance bug and solves an issue with signed MIME parts. + - Issue #20540: Fix a performance regression (vs. Python 3.2) when layering a multiprocessing Connection over a TCP socket. For small payloads, Nagle's algorithm would introduce idle delays before the entire transmission of a -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 00:18:39 2014 From: python-checkins at python.org (nick.coghlan) Date: Sun, 9 Feb 2014 00:18:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320563=3A_Declare_?= =?utf-8?q?ipaddress_API_stable?= Message-ID: <3fM8Sv4Q4zz7LjN@mail.python.org> http://hg.python.org/cpython/rev/2b9c10f3b969 changeset: 89070:2b9c10f3b969 user: Nick Coghlan date: Sun Feb 09 09:18:26 2014 +1000 summary: Close #20563: Declare ipaddress API stable files: Doc/library/ipaddress.rst | 7 ------- Doc/whatsnew/3.4.rst | 11 +++++++++++ Misc/NEWS | 2 ++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -9,13 +9,6 @@ -------------- -.. note:: - - The ``ipaddress`` module has been included in the standard library on a - :term:`provisional basis `. Backwards incompatible - changes (up to and including removal of the package) may occur if deemed - necessary by the core developers. - :mod:`ipaddress` provides the capabilities to create, manipulate and operate on IPv4 and IPv6 addresses and networks. diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -134,6 +134,7 @@ handling ` (:issue:`18891`). * :mod:`plistlib` has a cleaned up interface and support for binary plist files (:issue:`14455`) +* The :mod:`ipaddress` module API has been declared stable CPython implementation improvements: @@ -840,6 +841,16 @@ by Stefan Behnel and Yury Selivanov in :issue:`17159`) +ipaddress +--------- + +:mod:`ipaddress` was added to the standard library in Python 3.3 as a +:term:`provisional API`. With the release of Python 3.4, this qualification +has been removed: :mod:`ipaddress` is now considered a stable API, covered +by the normal standard library requirements to maintain backwards +compatibility. + + logging ------- diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,8 @@ Library ------- +- Issue #20563: The ipaddress module API is now considered stable. + - Issue #14983: email.generator now always adds a line end after each MIME boundary marker, instead of doing so only when there is an epilogue. This fixes an RFC compliance bug and solves an issue with signed MIME parts. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 01:10:39 2014 From: python-checkins at python.org (nick.coghlan) Date: Sun, 9 Feb 2014 01:10:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Tweaks_to_What=27s_New_and?= =?utf-8?q?_some_referenced_docs?= Message-ID: <3fM9cv0Lvlz7Lmr@mail.python.org> http://hg.python.org/cpython/rev/254b4bb1de9e changeset: 89071:254b4bb1de9e user: Nick Coghlan date: Sun Feb 09 10:10:24 2014 +1000 summary: Tweaks to What's New and some referenced docs files: Doc/c-api/type.rst | 2 +- Doc/library/venv.rst | 3 +- Doc/whatsnew/3.4.rst | 50 +++++++++++++++++++++++-------- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -100,7 +100,7 @@ .. c:function:: void* PyType_GetSlot(PyTypeObject *type, int slot) - Return the function pointer stored int the given slot. If the + Return the function pointer stored in the given slot. If the result is *NULL*, this indicates that either the slot is *NULL*, or that the function was called with invalid parameters. Callers will typically cast the result pointer into the appropriate diff --git a/Doc/library/venv.rst b/Doc/library/venv.rst --- a/Doc/library/venv.rst +++ b/Doc/library/venv.rst @@ -107,7 +107,8 @@ upgraded in-place (defaults to ``False``). * ``with_pip`` -- a Boolean value which, if true, ensures pip is - installed in the virtual environment + installed in the virtual environment. This uses :mod:`ensurepip` with + the ``--default-pip`` option. .. versionchanged:: 3.4 Added the ``with_pip`` parameter diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -69,8 +69,9 @@ `changelog `_. .. note:: Prerelease users should be aware that this document is currently in - draft form. It will be updated substantially as Python 3.4 moves towards - release, so it's worth checking back even after reading earlier versions. + draft form. While it should be close to complete for the Python 3.4 + release candidates, adjustments and additions to the document may be made + up until the final release. .. seealso:: @@ -132,10 +133,9 @@ a new :mod:`~email.message.Message` subclass (:class:`~email.contentmanager.EmailMessage`) that :ref:`simplify MIME handling ` (:issue:`18891`). -* :mod:`plistlib` has a cleaned up interface and support for binary - plist files (:issue:`14455`) * The :mod:`ipaddress` module API has been declared stable + CPython implementation improvements: * :ref:`Safe object finalization ` (:pep:`442`). @@ -163,9 +163,13 @@ -------------------------------------------------------------- The new :mod:`ensurepip` module (defined in :pep:`453`) provides a standard -cross-platform mechanism to boostrap the pip installer into Python +cross-platform mechanism to bootstrap the pip installer into Python installations and virtual environments. +By default, the scripts ``pipX`` and ``pipX.Y`` will be installed (where +X.Y stands for the version of the Python installation), along with the +``pip`` Python package and its dependencies. + The :mod:`venv` module and the :command:`pyvenv` utility make use of this module to make ``pip`` readily available in virtual environments. When using the command line interface, ``pip`` is installed by default, while @@ -187,12 +191,13 @@ .. note:: - The implementation of PEP 453 is still a work in progress. Refer to - :issue:`19347` for the progress on additional steps: - - * Having the binary installers install ``pip`` by default - * Recommending the use of ``pip`` in the "Installing Python Module" - documentation. + To avoid conflicts between parallel Python 2 and Python 3 installations, + only the versioned ``pip3`` and ``pip3.4`` commands are bootstrapped by + default when ``ensurepip`` is invoked directly (including by the CPython + installers). ``pyvenv`` ensures that the unqualified ``pip`` command is + made available in virtual environments, and ``pip`` can always be + invoked via the ``-m`` switch rather than directly to avoid ambiguity on + systems with multiple Python installations. .. seealso:: @@ -257,6 +262,11 @@ File "", line 1, in LookupError: 'rot13' is not a text encoding; use codecs.encode() to handle arbitrary codecs + >>> open("foo.txt", encoding="hex") + Traceback (most recent call last): + File "", line 1, in + LookupError: 'hex' is not a text encoding; use codecs.open() to handle arbitrary codecs + In a related change, whenever it is feasible without breaking backwards compatibility, exceptions raised during encoding and decoding operations will be wrapped in a chained exception of the same type that mentions the @@ -308,6 +318,7 @@ (Contributed by Nick Coghlan in :issue:`7475`, , :issue:`17827`, :issue:`17828` and :issue:`19619`) + .. _whatsnew-pep-451: PEP 451: A ModuleSpec Type for the Import System @@ -959,8 +970,6 @@ pickle ------ -protocol 4 - :mod:`pickle` now supports (but does not use by default) a new pickle protocol, protocol 4. This new protocol addresses a number of issues that were present in previous protocols, such as the serialization of nested classes, very large @@ -973,6 +982,14 @@ PEP written by Antoine Pitrou and implemented by Alexandre Vassalotti. +plistlib +-------- + +:mod:`plistlib` now supports binary plist files, and offers the common +``load``/``loads``/``dump``/``dumps`` API pattern for serialization formats +(Contributed by Ronald Oussoren and others in :issue:`14455`). + + poplib ------ @@ -1354,6 +1371,9 @@ accurate signatures for builtins and standard library extension modules implemented in C. +Some standard library extension modules have been converted to use Argument +Clinic in Python 3.4, and :mod:`inspect` has been updated accordingly. + .. note:: The Argument Clinic PEP is not fully up to date with the state of the implementation. This has been deemed acceptable by the release manager @@ -1369,6 +1389,10 @@ Other Build and C API Changes ----------------------------- +* The new :c:func:`PyType_GetSlot` function has been added to the stable ABI, + allowing retrieval of function pointers from named type slots when using + the limited API. (Contributed by Martin von L?wis in :issue:`17162`) + * The new :c:func:`Py_SetStandardStreamEncoding` pre-initialization API allows applications embedding the CPython interpreter to reliably force a particular encoding and error handler for the standard streams -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 01:26:31 2014 From: python-checkins at python.org (victor.stinner) Date: Sun, 9 Feb 2014 01:26:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_tests=3A_Remove_sc?= =?utf-8?q?ories_of_resolution/granularity?= Message-ID: <3fM9zC4hvQz7LjM@mail.python.org> http://hg.python.org/cpython/rev/53de17e05d05 changeset: 89072:53de17e05d05 user: Victor Stinner date: Sun Feb 09 01:25:52 2014 +0100 summary: asyncio tests: Remove scories of resolution/granularity files: Lib/test/test_asyncio/test_proactor_events.py | 2 -- Lib/test/test_asyncio/test_selector_events.py | 1 - 2 files changed, 0 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -17,7 +17,6 @@ def setUp(self): self.loop = test_utils.TestLoop() self.proactor = unittest.mock.Mock() - self.proactor.resolution = 1e-3 self.loop._proactor = self.proactor self.protocol = test_utils.make_test_protocol(asyncio.Protocol) self.sock = unittest.mock.Mock(socket.socket) @@ -343,7 +342,6 @@ def setUp(self): self.sock = unittest.mock.Mock(socket.socket) self.proactor = unittest.mock.Mock() - self.proactor.resolution = 1e-3 self.ssock, self.csock = unittest.mock.Mock(), unittest.mock.Mock() diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -39,7 +39,6 @@ def setUp(self): selector = unittest.mock.Mock() - selector.resolution = 1e-3 self.loop = TestBaseSelectorEventLoop(selector) def test_make_socket_transport(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 01:35:38 2014 From: python-checkins at python.org (victor.stinner) Date: Sun, 9 Feb 2014 01:35:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_fix_gather?= =?utf-8?b?KCkgZG9j?= Message-ID: <3fMB9k2MP3z7Lk8@mail.python.org> http://hg.python.org/cpython/rev/df5f692e9368 changeset: 89073:df5f692e9368 user: Victor Stinner date: Sun Feb 09 01:35:24 2014 +0100 summary: asyncio doc: fix gather() doc files: Doc/library/asyncio-task.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -415,7 +415,7 @@ All futures must share the same event loop. If all the tasks are done successfully, the returned future's result is the list of results (in the order of the original sequence, not necessarily the order of results - arrival). If *result_exception* is True, exceptions in the tasks are + arrival). If *return_exceptions* is True, exceptions in the tasks are treated the same as successful results, and gathered in the result list; otherwise, the first raised exception will be immediately propagated to the returned future. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 01:37:04 2014 From: python-checkins at python.org (brian.curtin) Date: Sun, 9 Feb 2014 01:37:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Spelling_corrections=2E_Su?= =?utf-8?q?bmitted_to_python-dev_by_python=40mrabarnett=2Eplus=2Ecom?= Message-ID: <3fMBCN1mbGz7Lk1@mail.python.org> http://hg.python.org/cpython/rev/3cfaeb788e00 changeset: 89074:3cfaeb788e00 parent: 89072:53de17e05d05 user: Brian Curtin date: Sat Feb 08 18:36:14 2014 -0600 summary: Spelling corrections. Submitted to python-dev by python at mrabarnett.plus.com files: Doc/library/asyncio-protocol.rst | 2 +- Doc/library/asyncio-subprocess.rst | 6 +++--- Doc/library/asyncio-task.rst | 4 ++-- Doc/library/asyncio.rst | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -194,7 +194,7 @@ .. method:: get_pipe_transport(fd) - Return the transport for the communication pipe correspondong to the + Return the transport for the communication pipe corresponding to the integer file descriptor *fd*. The return value can be a readable or writable streaming transport, depending on the *fd*. If *fd* doesn't correspond to a pipe belonging to this transport, :const:`None` is diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -3,8 +3,8 @@ Subprocess ========== -Create a subproces ------------------- +Create a subprocess +------------------- .. function:: create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds) @@ -116,7 +116,7 @@ Kills the child. On Posix OSs the function sends :py:data:`SIGKILL` to the child. On Windows :meth:`kill` is an alias for :meth:`terminate`. - .. method:: send_signal(signale) + .. method:: send_signal(signal) Sends the signal *signal* to the child process. diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -111,7 +111,7 @@ loop.close() ``compute()`` is chained to ``print_sum()``: ``print_sum()`` coroutine waits -until ``compute()`` is completed before returing its result. +until ``compute()`` is completed before returning its result. Sequence diagram of the example: @@ -315,7 +315,7 @@ The frames are always ordered from oldest to newest. - The optional limit gives the maximum nummber of frames to return; by + The optional limit gives the maximum number of frames to return; by default all available frames are returned. Its meaning differs depending on whether a stack or a traceback is returned: the newest frames of a stack are returned, but the oldest frames of a traceback are returned. diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst --- a/Doc/library/asyncio.rst +++ b/Doc/library/asyncio.rst @@ -24,7 +24,7 @@ * concrete support for TCP, UDP, SSL, subprocess pipes, delayed calls, and others (some may be system-dependent); -* a :class:`Future` class that mimicks the one in the :mod:`concurrent.futures` +* a :class:`Future` class that mimics the one in the :mod:`concurrent.futures` module, but adapted for use with the event loop; * coroutines and tasks based on ``yield from`` (:PEP:`380`), to help write -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 01:37:05 2014 From: python-checkins at python.org (brian.curtin) Date: Sun, 9 Feb 2014 01:37:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3fMBCP3X9jz7Lk1@mail.python.org> http://hg.python.org/cpython/rev/435350b76922 changeset: 89075:435350b76922 parent: 89074:3cfaeb788e00 parent: 89073:df5f692e9368 user: Brian Curtin date: Sat Feb 08 18:36:57 2014 -0600 summary: merge files: Doc/library/asyncio-task.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -415,7 +415,7 @@ All futures must share the same event loop. If all the tasks are done successfully, the returned future's result is the list of results (in the order of the original sequence, not necessarily the order of results - arrival). If *result_exception* is True, exceptions in the tasks are + arrival). If *return_exceptions* is True, exceptions in the tasks are treated the same as successful results, and gathered in the result list; otherwise, the first raised exception will be immediately propagated to the returned future. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 01:47:12 2014 From: python-checkins at python.org (nick.coghlan) Date: Sun, 9 Feb 2014 01:47:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320500=3A_Don=27t_?= =?utf-8?q?trigger_PyObject=5FStr_assertion_at_shutdown?= Message-ID: <3fMBR46KlYz7Lk1@mail.python.org> http://hg.python.org/cpython/rev/e7708864a8d5 changeset: 89076:e7708864a8d5 user: Nick Coghlan date: Sun Feb 09 10:43:21 2014 +1000 summary: Close #20500: Don't trigger PyObject_Str assertion at shutdown files: Lib/test/test_cmd_line_script.py | 18 ++++++++++++++++++ Misc/NEWS | 5 ++++- Objects/object.c | 2 +- Python/pythonrun.c | 5 +++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -405,6 +405,24 @@ 'stdout=%r stderr=%r' % (stdout, stderr)) self.assertEqual(0, rc) + def test_issue20500_exit_with_exception_value(self): + script = textwrap.dedent("""\ + import sys + error = None + try: + raise ValueError('some text') + except ValueError as err: + error = err + + if error: + sys.exit(error) + """) + with temp_dir() as script_dir: + script_name = _make_test_script(script_dir, 'script', script) + exitcode, stdout, stderr = assert_python_failure(script_name) + text = stderr.decode('ascii') + self.assertEqual(text, "some text") + def test_main(): support.run_unittest(CmdLineTest) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,7 +10,10 @@ Core and Builtins ----------------- -- Issue #20538: UTF-7 incremental decoder produced inconsistant string when +- Issue #20500: Displaying an exception at interpreter shutdown no longer + risks triggering an assertion failure in PyObject_Str. + +- Issue #20538: UTF-7 incremental decoder produced inconsistent string when input was truncated in BASE64 section. - Issue #20404: io.TextIOWrapper (and hence the open() builtin) now uses the diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -508,7 +508,7 @@ #ifdef Py_DEBUG /* PyObject_Str() must not be called with an exception set, because it may clear it (directly or indirectly) and so the - caller looses its exception */ + caller loses its exception */ assert(!PyErr_Occurred()); #endif diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1792,6 +1792,11 @@ exitcode = (int)PyLong_AsLong(value); else { PyObject *sys_stderr = _PySys_GetObjectId(&PyId_stderr); + /* We clear the exception here to avoid triggering the assertion + * in PyObject_Str that ensures it won't silently lose exception + * details. + */ + PyErr_Clear(); if (sys_stderr != NULL && sys_stderr != Py_None) { PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW); } else { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 01:57:47 2014 From: python-checkins at python.org (nick.coghlan) Date: Sun, 9 Feb 2014 01:57:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Note_the_new_debug_asserti?= =?utf-8?q?on_in_PyObject=5FStr?= Message-ID: <3fMBgH5vjvz7Ljl@mail.python.org> http://hg.python.org/cpython/rev/2b3b298091fa changeset: 89077:2b3b298091fa user: Nick Coghlan date: Sun Feb 09 10:57:34 2014 +1000 summary: Note the new debug assertion in PyObject_Str files: Doc/c-api/object.rst | 4 ++++ Doc/whatsnew/3.4.rst | 7 +++++++ 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -170,6 +170,10 @@ Python expression ``str(o)``. Called by the :func:`str` built-in function and, therefore, by the :func:`print` function. + .. versionchanged:: 3.4 + This function now includes a debug assertion that ensures it does not + silently discard an active exception. + .. c:function:: PyObject* PyObject_Bytes(PyObject *o) .. index:: builtin: bytes diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1708,6 +1708,13 @@ Changes in the C API -------------------- +* :c:func:`PyObject_Str` now includes a debug assertion that ensures it will + no longer silently discard currently active exceptions. In cases where + discarding the active exception is expected and desired (for example, + because it has already been saved locally with :c:func:`PyErr_Fetch`), an + explicit :c:func:`PyErr_Clear` call will be needed to avoid triggering the + assertion. + * :c:func:`PyErr_SetImportError` now sets :exc:`TypeError` when its **msg** argument is not set. Previously only ``NULL`` was returned with no exception set. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 02:35:52 2014 From: python-checkins at python.org (guido.van.rossum) Date: Sun, 9 Feb 2014 02:35:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Test_fix=2E?= Message-ID: <3fMCWD4MbBz7LjM@mail.python.org> http://hg.python.org/cpython/rev/a5dea12a45a1 changeset: 89078:a5dea12a45a1 user: Guido van Rossum date: Sat Feb 08 17:35:09 2014 -0800 summary: asyncio: Test fix. files: Lib/test/test_asyncio/test_tasks.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -860,7 +860,7 @@ def runner(): result = [] c = coro('ham') - for f in asyncio.as_completed({c, c, coro('spam')}, loop=self.loop): + for f in asyncio.as_completed([c, c, coro('spam')], loop=self.loop): result.append((yield from f)) return result -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 02:52:10 2014 From: python-checkins at python.org (victor.stinner) Date: Sun, 9 Feb 2014 02:52:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Remove_Process?= =?utf-8?q?=2Esubprocess_attribute=3B_it=27s_too_easy_to_get_inconsistent?= Message-ID: <3fMCt20pxDz7Lld@mail.python.org> http://hg.python.org/cpython/rev/8e00345c3b30 changeset: 89079:8e00345c3b30 user: Victor Stinner date: Sun Feb 09 02:51:40 2014 +0100 summary: asyncio: Remove Process.subprocess attribute; it's too easy to get inconsistent Process and Popen objects files: Doc/library/asyncio-subprocess.rst | 6 +--- Lib/asyncio/subprocess.py | 4 -- Lib/test/test_asyncio/test_subprocess.py | 20 ------------ 3 files changed, 1 insertions(+), 29 deletions(-) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -87,10 +87,6 @@ Standard error stream (read), ``None`` if the process was created with ``stderr=None``. - .. attribute:: subprocess - - Underlying :class:`subprocess.Popen` object. - .. method:: communicate(input=None) Interact with process: Send data to stdin. Read data from stdout and @@ -102,7 +98,7 @@ :meth:`communicate` returns a tuple ``(stdoutdata, stderrdata)``. Note that if you want to send data to the process's stdin, you need to - create the Popen object with ``stdin=PIPE``. Similarly, to get anything + create the Process object with ``stdin=PIPE``. Similarly, to get anything other than ``None`` in the result tuple, you need to give ``stdout=PIPE`` and/or ``stderr=PIPE`` too. diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -106,10 +106,6 @@ yield from waiter return waiter.result() - @property - def subprocess(self): - return self._transport.get_extra_info('subprocess') - def _check_alive(self): if self._transport.get_returncode() is not None: raise ProcessLookupError() diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -7,9 +7,6 @@ if sys.platform != 'win32': from asyncio import unix_events -# Program exiting quickly -PROGRAM_EXIT_FAST = [sys.executable, '-c', 'pass'] - # Program blocking PROGRAM_BLOCKED = [sys.executable, '-c', 'import time; time.sleep(3600)'] @@ -119,23 +116,6 @@ returncode = self.loop.run_until_complete(proc.wait()) self.assertEqual(-signal.SIGHUP, returncode) - def test_subprocess(self): - args = PROGRAM_EXIT_FAST - - @asyncio.coroutine - def run(): - proc = yield from asyncio.create_subprocess_exec(*args, - loop=self.loop) - yield from proc.wait() - # need to poll subprocess.Popen, otherwise the returncode - # attribute is not set - proc.subprocess.wait() - return proc - - proc = self.loop.run_until_complete(run()) - self.assertEqual(proc.subprocess.returncode, proc.returncode) - self.assertEqual(proc.subprocess.pid, proc.pid) - def test_broken_pipe(self): large_data = b'x' * support.PIPE_MAX_SIZE -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 03:01:03 2014 From: python-checkins at python.org (nick.coghlan) Date: Sun, 9 Feb 2014 03:01:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320500=3A_Note_oth?= =?utf-8?q?er_public_APIs_with_the_new_assertion?= Message-ID: <3fMD4H73rmz7LjM@mail.python.org> http://hg.python.org/cpython/rev/41023a501c7b changeset: 89080:41023a501c7b user: Nick Coghlan date: Sun Feb 09 12:00:01 2014 +1000 summary: Issue #20500: Note other public APIs with the new assertion files: Doc/c-api/object.rst | 7 +++++-- Doc/c-api/veryhigh.rst | 4 ++++ Doc/whatsnew/3.4.rst | 14 +++++++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -149,6 +149,9 @@ representation on success, *NULL* on failure. This is the equivalent of the Python expression ``repr(o)``. Called by the :func:`repr` built-in function. + .. versionchanged:: 3.4 + This function now includes a debug assertion to help ensure that it + does not silently discard an active exception. .. c:function:: PyObject* PyObject_ASCII(PyObject *o) @@ -171,8 +174,8 @@ and, therefore, by the :func:`print` function. .. versionchanged:: 3.4 - This function now includes a debug assertion that ensures it does not - silently discard an active exception. + This function now includes a debug assertion to help ensure that it + does not silently discard an active exception. .. c:function:: PyObject* PyObject_Bytes(PyObject *o) diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst --- a/Doc/c-api/veryhigh.rst +++ b/Doc/c-api/veryhigh.rst @@ -322,6 +322,10 @@ it causes an exception to immediately be thrown; this is used for the :meth:`~generator.throw` methods of generator objects. + .. versionchanged:: 3.4 + This function now includes a debug assertion to help ensure that it + does not silently discard an active exception. + .. c:function:: int PyEval_MergeCompilerFlags(PyCompilerFlags *cf) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1708,12 +1708,16 @@ Changes in the C API -------------------- -* :c:func:`PyObject_Str` now includes a debug assertion that ensures it will - no longer silently discard currently active exceptions. In cases where +* :c:func:`PyEval_EvalFrameEx`, :c:func:`PyObject_Repr(), and + :c:func:`PyObject_Str`, along with some other internal C APIs, now include + a debugging assertion that ensures they are not used in situations where + they may silently discard a currently active exception. In cases where discarding the active exception is expected and desired (for example, - because it has already been saved locally with :c:func:`PyErr_Fetch`), an - explicit :c:func:`PyErr_Clear` call will be needed to avoid triggering the - assertion. + because it has already been saved locally with :c:func:`PyErr_Fetch` or + is being deliberately replaced with a different exception), an explicit + :c:func:`PyErr_Clear` call will be needed to avoid triggering the + assertion when running against a version of Python that is compiled with + assertions enabled. * :c:func:`PyErr_SetImportError` now sets :exc:`TypeError` when its **msg** argument is not set. Previously only ``NULL`` was returned with no exception -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 03:05:26 2014 From: python-checkins at python.org (nick.coghlan) Date: Sun, 9 Feb 2014 03:05:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320500=3A_clarify_?= =?utf-8?q?that_invocation_may_be_indirect?= Message-ID: <3fMD9L2qSFz7LjM@mail.python.org> http://hg.python.org/cpython/rev/9e7594d65178 changeset: 89081:9e7594d65178 user: Nick Coghlan date: Sun Feb 09 12:05:13 2014 +1000 summary: Issue #20500: clarify that invocation may be indirect files: Doc/whatsnew/3.4.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1716,8 +1716,9 @@ because it has already been saved locally with :c:func:`PyErr_Fetch` or is being deliberately replaced with a different exception), an explicit :c:func:`PyErr_Clear` call will be needed to avoid triggering the - assertion when running against a version of Python that is compiled with - assertions enabled. + assertion when invoking these operations (directly or indirectly) and + running against a version of Python that is compiled with assertions + enabled. * :c:func:`PyErr_SetImportError` now sets :exc:`TypeError` when its **msg** argument is not set. Previously only ``NULL`` was returned with no exception -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 04:44:11 2014 From: python-checkins at python.org (guido.van.rossum) Date: Sun, 9 Feb 2014 04:44:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Remove_more_rel?= =?utf-8?q?ics_of_resolution/granularity=2E?= Message-ID: <3fMGMH3KVjz7LjN@mail.python.org> http://hg.python.org/cpython/rev/346e507b2cfb changeset: 89082:346e507b2cfb user: Guido van Rossum date: Sat Feb 08 19:44:02 2014 -0800 summary: asyncio: Remove more relics of resolution/granularity. files: Lib/asyncio/test_utils.py | 5 ----- Lib/asyncio/windows_events.py | 1 - 2 files changed, 0 insertions(+), 6 deletions(-) diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -144,10 +144,6 @@ def __init__(self): self.keys = {} - @property - def resolution(self): - return 1e-3 - def register(self, fileobj, events, data=None): key = selectors.SelectorKey(fileobj, 0, events, data) self.keys[fileobj] = key @@ -196,7 +192,6 @@ next(self._gen) self._time = 0 self._timers = [] - self._granularity = 1e-9 self._selector = TestSelector() self.readers = {} diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -191,7 +191,6 @@ self._cache = {} self._registered = weakref.WeakSet() self._stopped_serving = weakref.WeakSet() - self.resolution = 1e-3 def set_loop(self, loop): self._loop = loop -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 07:16:12 2014 From: python-checkins at python.org (larry.hastings) Date: Sun, 9 Feb 2014 07:16:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320530=3A_Argument?= =?utf-8?q?_Clinic=27s_signature_format_has_been_revised_again=2E?= Message-ID: <3fMKkh2HNZz7Ljm@mail.python.org> http://hg.python.org/cpython/rev/29d9638bf449 changeset: 89083:29d9638bf449 user: Larry Hastings date: Sat Feb 08 22:15:29 2014 -0800 summary: Issue #20530: Argument Clinic's signature format has been revised again. The new syntax is highly human readable while still preventing false positives. The syntax also extends Python syntax to denote "self" and positional-only parameters, allowing inspect.Signature objects to be totally accurate for all supported builtins in Python 3.4. files: Include/object.h | 4 +- Lib/inspect.py | 117 +++++++++-- Lib/test/test_capi.py | 17 +- Lib/test/test_inspect.py | 73 ++++++- Misc/NEWS | 16 +- Modules/_cryptmodule.c | 6 +- Modules/_datetimemodule.c | 6 +- Modules/_dbmmodule.c | 12 +- Modules/_opcode.c | 6 +- Modules/_sre.c | 6 +- Modules/_testcapimodule.c | 27 ++- Modules/_weakref.c | 6 +- Modules/clinic/_bz2module.c.h | 22 +- Modules/clinic/_lzmamodule.c.h | 30 ++- Modules/clinic/_pickle.c.h | 68 +++++- Modules/clinic/audioop.c.h | 107 ++++++++-- Modules/clinic/binascii.c.h | 58 ++++- Modules/clinic/zlibmodule.c.h | 52 +++- Modules/posixmodule.c | 19 +- Modules/unicodedata.c | 6 +- Objects/descrobject.c | 12 +- Objects/dictobject.c | 12 +- Objects/methodobject.c | 4 +- Objects/typeobject.c | 205 ++++++++++++-------- Objects/unicodeobject.c | 6 +- Python/import.c | 72 ++++-- Tools/clinic/clinic.py | 162 +++++++++++---- Tools/clinic/clinic_test.py | 43 +++- 28 files changed, 836 insertions(+), 338 deletions(-) diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -496,8 +496,8 @@ PyAPI_FUNC(void) PyType_Modified(PyTypeObject *); #ifndef Py_LIMITED_API -PyAPI_FUNC(PyObject *) _PyType_GetDocFromInternalDoc(const char *); -PyAPI_FUNC(PyObject *) _PyType_GetTextSignatureFromInternalDoc(const char *); +PyAPI_FUNC(PyObject *) _PyType_GetDocFromInternalDoc(const char *, const char *); +PyAPI_FUNC(PyObject *) _PyType_GetTextSignatureFromInternalDoc(const char *, const char *); #endif /* Generic operations on objects */ diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -39,6 +39,7 @@ import re import sys import tokenize +import token import types import warnings import functools @@ -1648,25 +1649,88 @@ return spec[2:pos] +def _signature_strip_non_python_syntax(signature): + """ + Takes a signature in Argument Clinic's extended signature format. + Returns a tuple of three things: + * that signature re-rendered in standard Python syntax, + * the index of the "self" parameter (generally 0), or None if + the function does not have a "self" parameter, and + * the index of the last "positional only" parameter, + or None if the signature has no positional-only parameters. + """ + + if not signature: + return signature, None, None + + self_parameter = None + last_positional_only = None + + lines = [l.encode('ascii') for l in signature.split('\n')] + generator = iter(lines).__next__ + token_stream = tokenize.tokenize(generator) + + delayed_comma = False + skip_next_comma = False + text = [] + add = text.append + + current_parameter = 0 + OP = token.OP + ERRORTOKEN = token.ERRORTOKEN + + # token stream always starts with ENCODING token, skip it + t = next(token_stream) + assert t.type == tokenize.ENCODING + + for t in token_stream: + type, string = t.type, t.string + + if type == OP: + if string == ',': + if skip_next_comma: + skip_next_comma = False + else: + assert not delayed_comma + delayed_comma = True + current_parameter += 1 + continue + + if string == '/': + assert not skip_next_comma + assert last_positional_only is None + skip_next_comma = True + last_positional_only = current_parameter - 1 + continue + + if (type == ERRORTOKEN) and (string == '$'): + assert self_parameter is None + self_parameter = current_parameter + continue + + if delayed_comma: + delayed_comma = False + if not ((type == OP) and (string == ')')): + add(', ') + add(string) + if (string == ','): + add(' ') + clean_signature = ''.join(text) + return clean_signature, self_parameter, last_positional_only + + def _signature_fromstr(cls, obj, s): # Internal helper to parse content of '__text_signature__' # and return a Signature based on it Parameter = cls._parameter_cls - if s.endswith("/)"): - kind = Parameter.POSITIONAL_ONLY - s = s[:-2] + ')' - else: - kind = Parameter.POSITIONAL_OR_KEYWORD - - first_parameter_is_self = s.startswith("($") - if first_parameter_is_self: - s = '(' + s[2:] - - s = "def foo" + s + ": pass" + clean_signature, self_parameter, last_positional_only = \ + _signature_strip_non_python_syntax(s) + + program = "def foo" + clean_signature + ": pass" try: - module = ast.parse(s) + module = ast.parse(program) except SyntaxError: module = None @@ -1750,8 +1814,14 @@ args = reversed(f.args.args) defaults = reversed(f.args.defaults) iter = itertools.zip_longest(args, defaults, fillvalue=None) - for name, default in reversed(list(iter)): + if last_positional_only is not None: + kind = Parameter.POSITIONAL_ONLY + else: + kind = Parameter.POSITIONAL_OR_KEYWORD + for i, (name, default) in enumerate(reversed(list(iter))): p(name, default) + if i == last_positional_only: + kind = Parameter.POSITIONAL_OR_KEYWORD # *args if f.args.vararg: @@ -1768,7 +1838,7 @@ kind = Parameter.VAR_KEYWORD p(f.args.kwarg, empty) - if first_parameter_is_self: + if self_parameter is not None: assert parameters if getattr(obj, '__self__', None): # strip off self, it's already been bound @@ -1861,12 +1931,13 @@ # At this point we know, that `obj` is a class, with no user- # defined '__init__', '__new__', or class-level '__call__' - for base in obj.__mro__: + for base in obj.__mro__[:-1]: # Since '__text_signature__' is implemented as a # descriptor that extracts text signature from the # class docstring, if 'obj' is derived from a builtin # class, its own '__text_signature__' may be 'None'. - # Therefore, we go through the MRO to find the first + # Therefore, we go through the MRO (except the last + # class in there, which is 'object') to find the first # class with non-empty text signature. try: text_sig = base.__text_signature__ @@ -1881,13 +1952,7 @@ # No '__text_signature__' was found for the 'obj' class. # Last option is to check if its '__init__' is # object.__init__ or type.__init__. - if type in obj.__mro__: - # 'obj' is a metaclass without user-defined __init__ - # or __new__. - if obj.__init__ is type.__init__: - # Return a signature of 'type' builtin. - return signature(type) - else: + if type not in obj.__mro__: # We have a class (not metaclass), but no user-defined # __init__ or __new__ for it if obj.__init__ is object.__init__: @@ -1901,7 +1966,11 @@ # infinite recursion (and even potential segfault) call = _signature_get_user_defined_method(type(obj), '__call__') if call is not None: - sig = signature(call) + try: + sig = signature(call) + except ValueError as ex: + msg = 'no signature found for {!r}'.format(obj) + raise ValueError(msg) from ex if sig is not None: # For classes and objects we skip the first parameter of their diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -126,20 +126,29 @@ self.assertEqual(_testcapi.docstring_no_signature.__text_signature__, None) self.assertEqual(_testcapi.docstring_with_invalid_signature.__doc__, - "sig= (module, boo)\n" + "docstring_with_invalid_signature($module, /, boo)\n" "\n" "This docstring has an invalid signature." ) self.assertEqual(_testcapi.docstring_with_invalid_signature.__text_signature__, None) + self.assertEqual(_testcapi.docstring_with_invalid_signature2.__doc__, + "docstring_with_invalid_signature2($module, /, boo)\n" + "\n" + "--\n" + "\n" + "This docstring also has an invalid signature." + ) + self.assertEqual(_testcapi.docstring_with_invalid_signature2.__text_signature__, None) + self.assertEqual(_testcapi.docstring_with_signature.__doc__, "This docstring has a valid signature.") - self.assertEqual(_testcapi.docstring_with_signature.__text_signature__, "(module, sig)") + self.assertEqual(_testcapi.docstring_with_signature.__text_signature__, "($module, /, sig)") self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__doc__, - "This docstring has a valid signature and some extra newlines.") + "\nThis docstring has a valid signature and some extra newlines.") self.assertEqual(_testcapi.docstring_with_signature_and_extra_newlines.__text_signature__, - "(module, parameter)") + "($module, /, parameter)") @unittest.skipUnless(threading, 'Threading required for this test.') diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1684,7 +1684,6 @@ self.assertEqual(p('sys'), sys.maxsize) self.assertEqual(p('exp'), sys.maxsize - 1) - test_callable(type) test_callable(object) # normal method @@ -1710,9 +1709,12 @@ # support for 'method-wrapper' test_callable(min.__call__) - class ThisWorksNow: - __call__ = type - test_callable(ThisWorksNow()) + # This doesn't work now. + # (We don't have a valid signature for "type" in 3.4) + with self.assertRaisesRegex(ValueError, "no signature found"): + class ThisWorksNow: + __call__ = type + test_callable(ThisWorksNow()) @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, @@ -2213,11 +2215,11 @@ # Test meta-classes without user-defined __init__ or __new__ class C(type): pass - self.assertEqual(str(inspect.signature(C)), - '(object_or_name, bases, dict)') class D(C): pass - self.assertEqual(str(inspect.signature(D)), - '(object_or_name, bases, dict)') + with self.assertRaisesRegex(ValueError, "callable.*is not supported"): + self.assertEqual(inspect.signature(C), None) + with self.assertRaisesRegex(ValueError, "callable.*is not supported"): + self.assertEqual(inspect.signature(D), None) @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") @@ -2768,6 +2770,61 @@ self.assertEqual(getter('($self, obj)'), 'self') self.assertEqual(getter('($cls, /, obj)'), 'cls') + def _strip_non_python_syntax(self, input, + clean_signature, self_parameter, last_positional_only): + computed_clean_signature, \ + computed_self_parameter, \ + computed_last_positional_only = \ + inspect._signature_strip_non_python_syntax(input) + self.assertEqual(computed_clean_signature, clean_signature) + self.assertEqual(computed_self_parameter, self_parameter) + self.assertEqual(computed_last_positional_only, last_positional_only) + + def test_signature_strip_non_python_syntax(self): + self._strip_non_python_syntax( + "($module, /, path, mode, *, dir_fd=None, " + + "effective_ids=False,\n follow_symlinks=True)", + "(module, path, mode, *, dir_fd=None, " + + "effective_ids=False, follow_symlinks=True)", + 0, + 0) + + self._strip_non_python_syntax( + "($module, word, salt, /)", + "(module, word, salt)", + 0, + 2) + + self._strip_non_python_syntax( + "(x, y=None, z=None, /)", + "(x, y=None, z=None)", + None, + 2) + + self._strip_non_python_syntax( + "(x, y=None, z=None)", + "(x, y=None, z=None)", + None, + None) + + self._strip_non_python_syntax( + "(x,\n y=None,\n z = None )", + "(x, y=None, z=None)", + None, + None) + + self._strip_non_python_syntax( + "", + "", + None, + None) + + self._strip_non_python_syntax( + None, + None, + None, + None) + class TestUnwrap(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -200,18 +200,24 @@ Tools/Demos ----------- -- #Issue 20456: Argument Clinic now observes the C preprocessor conditional +- Issue #20530: Argument Clinic's signature format has been revised again. + The new syntax is highly human readable while still preventing false + positives. The syntax also extends Python syntax to denote "self" and + positional-only parameters, allowing inspect.Signature objects to be + totally accurate for all supported builtins in Python 3.4. + +- Issue #20456: Argument Clinic now observes the C preprocessor conditional compilation statements of the C files it parses. When a Clinic block is inside a conditional code, it adjusts its output to match, including automatically generating an empty methoddef macro. -- #Issue 20456: Cloned functions in Argument Clinic now use the correct +- Issue #20456: Cloned functions in Argument Clinic now use the correct name, not the name of the function they were cloned from, for text strings inside generated code. -- #Issue 20456: Fixed Argument Clinic's test suite and "--converters" feature. - -- #Issue 20456: Argument Clinic now allows specifying different names +- Issue #20456: Fixed Argument Clinic's test suite and "--converters" feature. + +- Issue #20456: Argument Clinic now allows specifying different names for a parameter in Python and C, using "as" on the parameter line. - Issue #20326: Argument Clinic now uses a simple, unique signature to diff --git a/Modules/_cryptmodule.c b/Modules/_cryptmodule.c --- a/Modules/_cryptmodule.c +++ b/Modules/_cryptmodule.c @@ -30,7 +30,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(crypt_crypt__doc__, -"sig=($module, word, salt)\n" +"crypt($module, word, salt, /)\n" +"--\n" +"\n" "Hash a *word* with the given *salt* and return the hashed password.\n" "\n" "*word* will usually be a user\'s password. *salt* (either a random 2 or 16\n" @@ -63,7 +65,7 @@ static PyObject * crypt_crypt_impl(PyModuleDef *module, const char *word, const char *salt) -/*[clinic end generated code: output=c7443257e03fca92 input=4d93b6d0f41fbf58]*/ +/*[clinic end generated code: output=3eaacdf994a6ff23 input=4d93b6d0f41fbf58]*/ { /* On some platforms (AtheOS) crypt returns NULL for an invalid salt. Return None in that case. XXX Maybe raise an exception? */ diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -4159,7 +4159,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(datetime_datetime_now__doc__, -"sig=($type, tz=None)\n" +"now($type, /, tz=None)\n" +"--\n" +"\n" "Returns new datetime object representing current time local to tz.\n" "\n" " tz\n" @@ -4192,7 +4194,7 @@ static PyObject * datetime_datetime_now_impl(PyTypeObject *type, PyObject *tz) -/*[clinic end generated code: output=c8a47308483e579a input=80d09869c5267d00]*/ +/*[clinic end generated code: output=583c5637e3c843fa input=80d09869c5267d00]*/ { PyObject *self; diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -278,7 +278,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(dbm_dbm_get__doc__, -"sig=($self, key, default=None)\n" +"get($self, key, default=None, /)\n" +"--\n" +"\n" "Return the value for key if present, otherwise default."); #define DBM_DBM_GET_METHODDEF \ @@ -307,7 +309,7 @@ static PyObject * dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) -/*[clinic end generated code: output=2bbaf9a187f9b6bf input=aecf5efd2f2b1a3b]*/ +/*[clinic end generated code: output=452ea11394e7e92d input=aecf5efd2f2b1a3b]*/ { datum dbm_key, val; @@ -448,7 +450,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(dbmopen__doc__, -"sig=($module, filename, flags=\'r\', mode=0o666)\n" +"open($module, filename, flags=\'r\', mode=0o666, /)\n" +"--\n" +"\n" "Return a database object.\n" "\n" " filename\n" @@ -485,7 +489,7 @@ static PyObject * dbmopen_impl(PyModuleDef *module, const char *filename, const char *flags, int mode) -/*[clinic end generated code: output=a1da6a481d9d332b input=6499ab0fab1333ac]*/ +/*[clinic end generated code: output=9a7b725f9c4dcec2 input=6499ab0fab1333ac]*/ { int iflags; diff --git a/Modules/_opcode.c b/Modules/_opcode.c --- a/Modules/_opcode.c +++ b/Modules/_opcode.c @@ -18,7 +18,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_opcode_stack_effect__doc__, -"sig=($module, opcode, oparg=None)\n" +"stack_effect($module, opcode, oparg=None, /)\n" +"--\n" +"\n" "Compute the stack effect of the opcode."); #define _OPCODE_STACK_EFFECT_METHODDEF \ @@ -50,7 +52,7 @@ static int _opcode_stack_effect_impl(PyModuleDef *module, int opcode, PyObject *oparg) -/*[clinic end generated code: output=4fe636f5db87c0a9 input=2d0a9ee53c0418f5]*/ +/*[clinic end generated code: output=9e1133f8d587bc67 input=2d0a9ee53c0418f5]*/ { int effect; int oparg_int = 0; diff --git a/Modules/_sre.c b/Modules/_sre.c --- a/Modules/_sre.c +++ b/Modules/_sre.c @@ -540,7 +540,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(pattern_match__doc__, -"sig=($self, pattern, pos=0, endpos=sys.maxsize)\n" +"match($self, /, pattern, pos=0, endpos=sys.maxsize)\n" +"--\n" +"\n" "Matches zero or more characters at the beginning of the string."); #define PATTERN_MATCH_METHODDEF \ @@ -570,7 +572,7 @@ static PyObject * pattern_match_impl(PatternObject *self, PyObject *pattern, Py_ssize_t pos, Py_ssize_t endpos) -/*[clinic end generated code: output=9f5b785661677848 input=26f9fd31befe46b9]*/ +/*[clinic end generated code: output=1528eafdb8b025ad input=26f9fd31befe46b9]*/ { SRE_STATE state; Py_ssize_t status; diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2851,26 +2851,40 @@ ); PyDoc_STRVAR(docstring_with_invalid_signature, -"sig= (module, boo)\n" +"docstring_with_invalid_signature($module, /, boo)\n" "\n" "This docstring has an invalid signature." ); +PyDoc_STRVAR(docstring_with_invalid_signature2, +"docstring_with_invalid_signature2($module, /, boo)\n" +"\n" +"--\n" +"\n" +"This docstring also has an invalid signature." +); + PyDoc_STRVAR(docstring_with_signature, -"sig=(module, sig)\n" +"docstring_with_signature($module, /, sig)\n" +"--\n" +"\n" "This docstring has a valid signature." ); PyDoc_STRVAR(docstring_with_signature_and_extra_newlines, -"sig=(module, parameter)\n" -"\n" +"docstring_with_signature_and_extra_newlines($module, /, parameter)\n" +"--\n" "\n" "\n" "This docstring has a valid signature and some extra newlines." ); PyDoc_STRVAR(docstring_with_signature_with_defaults, -"sig=(module, s='avocado', b=b'bytes', d=3.14, i=35, n=None, t=True, f=False, local=the_number_three, sys=sys.maxsize, exp=sys.maxsize - 1)\n" +"docstring_with_signature_with_defaults(module, s='avocado',\n" +" b=b'bytes', d=3.14, i=35, n=None, t=True, f=False,\n" +" local=the_number_three, sys=sys.maxsize,\n" +" exp=sys.maxsize - 1)\n" +"--\n" "\n" "\n" "\n" @@ -3090,6 +3104,9 @@ {"docstring_with_invalid_signature", (PyCFunction)test_with_docstring, METH_NOARGS, docstring_with_invalid_signature}, + {"docstring_with_invalid_signature2", + (PyCFunction)test_with_docstring, METH_NOARGS, + docstring_with_invalid_signature2}, {"docstring_with_signature", (PyCFunction)test_with_docstring, METH_NOARGS, docstring_with_signature}, diff --git a/Modules/_weakref.c b/Modules/_weakref.c --- a/Modules/_weakref.c +++ b/Modules/_weakref.c @@ -20,7 +20,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_weakref_getweakrefcount__doc__, -"sig=($module, object)\n" +"getweakrefcount($module, object, /)\n" +"--\n" +"\n" "Return the number of weak references to \'object\'."); #define _WEAKREF_GETWEAKREFCOUNT_METHODDEF \ @@ -46,7 +48,7 @@ static Py_ssize_t _weakref_getweakrefcount_impl(PyModuleDef *module, PyObject *object) -/*[clinic end generated code: output=ef51baac56180816 input=cedb69711b6a2507]*/ +/*[clinic end generated code: output=032eedbfd7d69e10 input=cedb69711b6a2507]*/ { PyWeakReference **list; diff --git a/Modules/clinic/_bz2module.c.h b/Modules/clinic/_bz2module.c.h --- a/Modules/clinic/_bz2module.c.h +++ b/Modules/clinic/_bz2module.c.h @@ -3,7 +3,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_bz2_BZ2Compressor_compress__doc__, -"sig=($self, data)\n" +"compress($self, data, /)\n" +"--\n" +"\n" "Provide data to the compressor object.\n" "\n" "Returns a chunk of compressed data if possible, or b\'\' otherwise.\n" @@ -38,7 +40,9 @@ } PyDoc_STRVAR(_bz2_BZ2Compressor_flush__doc__, -"sig=($self)\n" +"flush($self, /)\n" +"--\n" +"\n" "Finish the compression process.\n" "\n" "Returns the compressed data left in internal buffers.\n" @@ -58,7 +62,9 @@ } PyDoc_STRVAR(_bz2_BZ2Compressor___init____doc__, -"sig=(compresslevel=9)\n" +"BZ2Compressor(compresslevel=9, /)\n" +"--\n" +"\n" "Create a compressor object for compressing data incrementally.\n" "\n" " compresslevel\n" @@ -89,7 +95,9 @@ } PyDoc_STRVAR(_bz2_BZ2Decompressor_decompress__doc__, -"sig=($self, data)\n" +"decompress($self, data, /)\n" +"--\n" +"\n" "Provide data to the decompressor object.\n" "\n" "Returns a chunk of decompressed data if possible, or b\'\' otherwise.\n" @@ -125,7 +133,9 @@ } PyDoc_STRVAR(_bz2_BZ2Decompressor___init____doc__, -"sig=()\n" +"BZ2Decompressor()\n" +"--\n" +"\n" "Create a decompressor object for decompressing data incrementally.\n" "\n" "For one-shot decompression, use the decompress() function instead."); @@ -149,4 +159,4 @@ exit: return return_value; } -/*[clinic end generated code: output=aca4f6329c1c773a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=21ca4405519a0931 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_lzmamodule.c.h b/Modules/clinic/_lzmamodule.c.h --- a/Modules/clinic/_lzmamodule.c.h +++ b/Modules/clinic/_lzmamodule.c.h @@ -3,7 +3,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_lzma_LZMACompressor_compress__doc__, -"sig=($self, data)\n" +"compress($self, data, /)\n" +"--\n" +"\n" "Provide data to the compressor object.\n" "\n" "Returns a chunk of compressed data if possible, or b\'\' otherwise.\n" @@ -38,7 +40,9 @@ } PyDoc_STRVAR(_lzma_LZMACompressor_flush__doc__, -"sig=($self)\n" +"flush($self, /)\n" +"--\n" +"\n" "Finish the compression process.\n" "\n" "Returns the compressed data left in internal buffers.\n" @@ -58,7 +62,9 @@ } PyDoc_STRVAR(_lzma_LZMADecompressor_decompress__doc__, -"sig=($self, data)\n" +"decompress($self, data, /)\n" +"--\n" +"\n" "Provide data to the decompressor object.\n" "\n" "Returns a chunk of decompressed data if possible, or b\'\' otherwise.\n" @@ -94,7 +100,9 @@ } PyDoc_STRVAR(_lzma_LZMADecompressor___init____doc__, -"sig=(format=FORMAT_AUTO, memlimit=None, filters=None)\n" +"LZMADecompressor(format=FORMAT_AUTO, memlimit=None, filters=None)\n" +"--\n" +"\n" "Create a decompressor object for decompressing data incrementally.\n" "\n" " format\n" @@ -137,7 +145,9 @@ } PyDoc_STRVAR(_lzma_is_check_supported__doc__, -"sig=($module, check_id)\n" +"is_check_supported($module, check_id, /)\n" +"--\n" +"\n" "Test whether the given integrity check is supported.\n" "\n" "Always returns True for CHECK_NONE and CHECK_CRC32."); @@ -165,7 +175,9 @@ } PyDoc_STRVAR(_lzma__encode_filter_properties__doc__, -"sig=($module, filter)\n" +"_encode_filter_properties($module, filter, /)\n" +"--\n" +"\n" "Return a bytes object encoding the options (properties) of the filter specified by *filter* (a dict).\n" "\n" "The result does not include the filter ID itself, only the options."); @@ -197,7 +209,9 @@ } PyDoc_STRVAR(_lzma__decode_filter_properties__doc__, -"sig=($module, filter_id, encoded_props)\n" +"_decode_filter_properties($module, filter_id, encoded_props, /)\n" +"--\n" +"\n" "Return a bytes object encoding the options (properties) of the filter specified by *filter* (a dict).\n" "\n" "The result does not include the filter ID itself, only the options."); @@ -228,4 +242,4 @@ return return_value; } -/*[clinic end generated code: output=fe63bc798a5c5c55 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=808fec8216ac712b input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_pickle.c.h b/Modules/clinic/_pickle.c.h --- a/Modules/clinic/_pickle.c.h +++ b/Modules/clinic/_pickle.c.h @@ -3,7 +3,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_pickle_Pickler_clear_memo__doc__, -"sig=($self)\n" +"clear_memo($self, /)\n" +"--\n" +"\n" "Clears the pickler\'s \"memo\".\n" "\n" "The memo is the data structure that remembers which objects the\n" @@ -24,14 +26,18 @@ } PyDoc_STRVAR(_pickle_Pickler_dump__doc__, -"sig=($self, obj)\n" +"dump($self, obj, /)\n" +"--\n" +"\n" "Write a pickled representation of the given object to the open file."); #define _PICKLE_PICKLER_DUMP_METHODDEF \ {"dump", (PyCFunction)_pickle_Pickler_dump, METH_O, _pickle_Pickler_dump__doc__}, PyDoc_STRVAR(_pickle_Pickler___init____doc__, -"sig=(file, protocol=None, fix_imports=True)\n" +"Pickler(file, protocol=None, fix_imports=True)\n" +"--\n" +"\n" "This takes a binary file for writing a pickle data stream.\n" "\n" "The optional *protocol* argument tells the pickler to use the given\n" @@ -74,7 +80,9 @@ } PyDoc_STRVAR(_pickle_PicklerMemoProxy_clear__doc__, -"sig=($self)\n" +"clear($self, /)\n" +"--\n" +"\n" "Remove all items from memo."); #define _PICKLE_PICKLERMEMOPROXY_CLEAR_METHODDEF \ @@ -90,7 +98,9 @@ } PyDoc_STRVAR(_pickle_PicklerMemoProxy_copy__doc__, -"sig=($self)\n" +"copy($self, /)\n" +"--\n" +"\n" "Copy the memo to a new object."); #define _PICKLE_PICKLERMEMOPROXY_COPY_METHODDEF \ @@ -106,7 +116,9 @@ } PyDoc_STRVAR(_pickle_PicklerMemoProxy___reduce____doc__, -"sig=($self)\n" +"__reduce__($self, /)\n" +"--\n" +"\n" "Implement pickle support."); #define _PICKLE_PICKLERMEMOPROXY___REDUCE___METHODDEF \ @@ -122,7 +134,9 @@ } PyDoc_STRVAR(_pickle_Unpickler_load__doc__, -"sig=($self)\n" +"load($self, /)\n" +"--\n" +"\n" "Load a pickle.\n" "\n" "Read a pickled object representation from the open file object given\n" @@ -142,7 +156,9 @@ } PyDoc_STRVAR(_pickle_Unpickler_find_class__doc__, -"sig=($self, module_name, global_name)\n" +"find_class($self, module_name, global_name, /)\n" +"--\n" +"\n" "Return an object from a specified module.\n" "\n" "If necessary, the module will be imported. Subclasses may override\n" @@ -176,7 +192,9 @@ } PyDoc_STRVAR(_pickle_Unpickler___init____doc__, -"sig=(file, *, fix_imports=True, encoding=\'ASCII\', errors=\'strict\')\n" +"Unpickler(file, *, fix_imports=True, encoding=\'ASCII\', errors=\'strict\')\n" +"--\n" +"\n" "This takes a binary file for reading a pickle data stream.\n" "\n" "The protocol version of the pickle is detected automatically, so no\n" @@ -222,7 +240,9 @@ } PyDoc_STRVAR(_pickle_UnpicklerMemoProxy_clear__doc__, -"sig=($self)\n" +"clear($self, /)\n" +"--\n" +"\n" "Remove all items from memo."); #define _PICKLE_UNPICKLERMEMOPROXY_CLEAR_METHODDEF \ @@ -238,7 +258,9 @@ } PyDoc_STRVAR(_pickle_UnpicklerMemoProxy_copy__doc__, -"sig=($self)\n" +"copy($self, /)\n" +"--\n" +"\n" "Copy the memo to a new object."); #define _PICKLE_UNPICKLERMEMOPROXY_COPY_METHODDEF \ @@ -254,7 +276,9 @@ } PyDoc_STRVAR(_pickle_UnpicklerMemoProxy___reduce____doc__, -"sig=($self)\n" +"__reduce__($self, /)\n" +"--\n" +"\n" "Implement pickling support."); #define _PICKLE_UNPICKLERMEMOPROXY___REDUCE___METHODDEF \ @@ -270,7 +294,9 @@ } PyDoc_STRVAR(_pickle_dump__doc__, -"sig=($module, obj, file, protocol=None, *, fix_imports=True)\n" +"dump($module, /, obj, file, protocol=None, *, fix_imports=True)\n" +"--\n" +"\n" "Write a pickled representation of obj to the open file object file.\n" "\n" "This is equivalent to ``Pickler(file, protocol).dump(obj)``, but may\n" @@ -320,7 +346,9 @@ } PyDoc_STRVAR(_pickle_dumps__doc__, -"sig=($module, obj, protocol=None, *, fix_imports=True)\n" +"dumps($module, /, obj, protocol=None, *, fix_imports=True)\n" +"--\n" +"\n" "Return the pickled representation of the object as a bytes object.\n" "\n" "The optional *protocol* argument tells the pickler to use the given\n" @@ -361,7 +389,10 @@ } PyDoc_STRVAR(_pickle_load__doc__, -"sig=($module, file, *, fix_imports=True, encoding=\'ASCII\', errors=\'strict\')\n" +"load($module, /, file, *, fix_imports=True, encoding=\'ASCII\',\n" +" errors=\'strict\')\n" +"--\n" +"\n" "Read and return an object from the pickle data stored in a file.\n" "\n" "This is equivalent to ``Unpickler(file).load()``, but may be more\n" @@ -413,7 +444,10 @@ } PyDoc_STRVAR(_pickle_loads__doc__, -"sig=($module, data, *, fix_imports=True, encoding=\'ASCII\', errors=\'strict\')\n" +"loads($module, /, data, *, fix_imports=True, encoding=\'ASCII\',\n" +" errors=\'strict\')\n" +"--\n" +"\n" "Read and return an object from the given pickle data.\n" "\n" "The protocol version of the pickle is detected automatically, so no\n" @@ -454,4 +488,4 @@ exit: return return_value; } -/*[clinic end generated code: output=c59d4dafc2646f11 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f965b6c7018c898d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/audioop.c.h b/Modules/clinic/audioop.c.h --- a/Modules/clinic/audioop.c.h +++ b/Modules/clinic/audioop.c.h @@ -3,7 +3,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(audioop_getsample__doc__, -"sig=($module, fragment, width, index)\n" +"getsample($module, fragment, width, index, /)\n" +"--\n" +"\n" "Return the value of sample index from the fragment."); #define AUDIOOP_GETSAMPLE_METHODDEF \ @@ -35,7 +37,9 @@ } PyDoc_STRVAR(audioop_max__doc__, -"sig=($module, fragment, width)\n" +"max($module, fragment, width, /)\n" +"--\n" +"\n" "Return the maximum of the absolute value of all samples in a fragment."); #define AUDIOOP_MAX_METHODDEF \ @@ -66,7 +70,9 @@ } PyDoc_STRVAR(audioop_minmax__doc__, -"sig=($module, fragment, width)\n" +"minmax($module, fragment, width, /)\n" +"--\n" +"\n" "Return the minimum and maximum values of all samples in the sound fragment."); #define AUDIOOP_MINMAX_METHODDEF \ @@ -97,7 +103,9 @@ } PyDoc_STRVAR(audioop_avg__doc__, -"sig=($module, fragment, width)\n" +"avg($module, fragment, width, /)\n" +"--\n" +"\n" "Return the average over all samples in the fragment."); #define AUDIOOP_AVG_METHODDEF \ @@ -128,7 +136,9 @@ } PyDoc_STRVAR(audioop_rms__doc__, -"sig=($module, fragment, width)\n" +"rms($module, fragment, width, /)\n" +"--\n" +"\n" "Return the root-mean-square of the fragment, i.e. sqrt(sum(S_i^2)/n)."); #define AUDIOOP_RMS_METHODDEF \ @@ -159,7 +169,9 @@ } PyDoc_STRVAR(audioop_findfit__doc__, -"sig=($module, fragment, reference)\n" +"findfit($module, fragment, reference, /)\n" +"--\n" +"\n" "Try to match reference as well as possible to a portion of fragment."); #define AUDIOOP_FINDFIT_METHODDEF \ @@ -193,7 +205,9 @@ } PyDoc_STRVAR(audioop_findfactor__doc__, -"sig=($module, fragment, reference)\n" +"findfactor($module, fragment, reference, /)\n" +"--\n" +"\n" "Return a factor F such that rms(add(fragment, mul(reference, -F))) is minimal."); #define AUDIOOP_FINDFACTOR_METHODDEF \ @@ -227,7 +241,9 @@ } PyDoc_STRVAR(audioop_findmax__doc__, -"sig=($module, fragment, length)\n" +"findmax($module, fragment, length, /)\n" +"--\n" +"\n" "Search fragment for a slice of specified number of samples with maximum energy."); #define AUDIOOP_FINDMAX_METHODDEF \ @@ -258,7 +274,9 @@ } PyDoc_STRVAR(audioop_avgpp__doc__, -"sig=($module, fragment, width)\n" +"avgpp($module, fragment, width, /)\n" +"--\n" +"\n" "Return the average peak-peak value over all samples in the fragment."); #define AUDIOOP_AVGPP_METHODDEF \ @@ -289,7 +307,9 @@ } PyDoc_STRVAR(audioop_maxpp__doc__, -"sig=($module, fragment, width)\n" +"maxpp($module, fragment, width, /)\n" +"--\n" +"\n" "Return the maximum peak-peak value in the sound fragment."); #define AUDIOOP_MAXPP_METHODDEF \ @@ -320,7 +340,9 @@ } PyDoc_STRVAR(audioop_cross__doc__, -"sig=($module, fragment, width)\n" +"cross($module, fragment, width, /)\n" +"--\n" +"\n" "Return the number of zero crossings in the fragment passed as an argument."); #define AUDIOOP_CROSS_METHODDEF \ @@ -351,7 +373,9 @@ } PyDoc_STRVAR(audioop_mul__doc__, -"sig=($module, fragment, width, factor)\n" +"mul($module, fragment, width, factor, /)\n" +"--\n" +"\n" "Return a fragment that has all samples in the original fragment multiplied by the floating-point value factor."); #define AUDIOOP_MUL_METHODDEF \ @@ -383,7 +407,9 @@ } PyDoc_STRVAR(audioop_tomono__doc__, -"sig=($module, fragment, width, lfactor, rfactor)\n" +"tomono($module, fragment, width, lfactor, rfactor, /)\n" +"--\n" +"\n" "Convert a stereo fragment to a mono fragment."); #define AUDIOOP_TOMONO_METHODDEF \ @@ -416,7 +442,9 @@ } PyDoc_STRVAR(audioop_tostereo__doc__, -"sig=($module, fragment, width, lfactor, rfactor)\n" +"tostereo($module, fragment, width, lfactor, rfactor, /)\n" +"--\n" +"\n" "Generate a stereo fragment from a mono fragment."); #define AUDIOOP_TOSTEREO_METHODDEF \ @@ -449,7 +477,9 @@ } PyDoc_STRVAR(audioop_add__doc__, -"sig=($module, fragment1, fragment2, width)\n" +"add($module, fragment1, fragment2, width, /)\n" +"--\n" +"\n" "Return a fragment which is the addition of the two samples passed as parameters."); #define AUDIOOP_ADD_METHODDEF \ @@ -484,7 +514,9 @@ } PyDoc_STRVAR(audioop_bias__doc__, -"sig=($module, fragment, width, bias)\n" +"bias($module, fragment, width, bias, /)\n" +"--\n" +"\n" "Return a fragment that is the original fragment with a bias added to each sample."); #define AUDIOOP_BIAS_METHODDEF \ @@ -516,7 +548,9 @@ } PyDoc_STRVAR(audioop_reverse__doc__, -"sig=($module, fragment, width)\n" +"reverse($module, fragment, width, /)\n" +"--\n" +"\n" "Reverse the samples in a fragment and returns the modified fragment."); #define AUDIOOP_REVERSE_METHODDEF \ @@ -547,7 +581,9 @@ } PyDoc_STRVAR(audioop_byteswap__doc__, -"sig=($module, fragment, width)\n" +"byteswap($module, fragment, width, /)\n" +"--\n" +"\n" "Convert big-endian samples to little-endian and vice versa."); #define AUDIOOP_BYTESWAP_METHODDEF \ @@ -578,7 +614,9 @@ } PyDoc_STRVAR(audioop_lin2lin__doc__, -"sig=($module, fragment, width, newwidth)\n" +"lin2lin($module, fragment, width, newwidth, /)\n" +"--\n" +"\n" "Convert samples between 1-, 2-, 3- and 4-byte formats."); #define AUDIOOP_LIN2LIN_METHODDEF \ @@ -610,7 +648,10 @@ } PyDoc_STRVAR(audioop_ratecv__doc__, -"sig=($module, fragment, width, nchannels, inrate, outrate, state, weightA=1, weightB=0)\n" +"ratecv($module, fragment, width, nchannels, inrate, outrate, state,\n" +" weightA=1, weightB=0, /)\n" +"--\n" +"\n" "Convert the frame rate of the input fragment."); #define AUDIOOP_RATECV_METHODDEF \ @@ -647,7 +688,9 @@ } PyDoc_STRVAR(audioop_lin2ulaw__doc__, -"sig=($module, fragment, width)\n" +"lin2ulaw($module, fragment, width, /)\n" +"--\n" +"\n" "Convert samples in the audio fragment to u-LAW encoding."); #define AUDIOOP_LIN2ULAW_METHODDEF \ @@ -678,7 +721,9 @@ } PyDoc_STRVAR(audioop_ulaw2lin__doc__, -"sig=($module, fragment, width)\n" +"ulaw2lin($module, fragment, width, /)\n" +"--\n" +"\n" "Convert sound fragments in u-LAW encoding to linearly encoded sound fragments."); #define AUDIOOP_ULAW2LIN_METHODDEF \ @@ -709,7 +754,9 @@ } PyDoc_STRVAR(audioop_lin2alaw__doc__, -"sig=($module, fragment, width)\n" +"lin2alaw($module, fragment, width, /)\n" +"--\n" +"\n" "Convert samples in the audio fragment to a-LAW encoding."); #define AUDIOOP_LIN2ALAW_METHODDEF \ @@ -740,7 +787,9 @@ } PyDoc_STRVAR(audioop_alaw2lin__doc__, -"sig=($module, fragment, width)\n" +"alaw2lin($module, fragment, width, /)\n" +"--\n" +"\n" "Convert sound fragments in a-LAW encoding to linearly encoded sound fragments."); #define AUDIOOP_ALAW2LIN_METHODDEF \ @@ -771,7 +820,9 @@ } PyDoc_STRVAR(audioop_lin2adpcm__doc__, -"sig=($module, fragment, width, state)\n" +"lin2adpcm($module, fragment, width, state, /)\n" +"--\n" +"\n" "Convert samples to 4 bit Intel/DVI ADPCM encoding."); #define AUDIOOP_LIN2ADPCM_METHODDEF \ @@ -803,7 +854,9 @@ } PyDoc_STRVAR(audioop_adpcm2lin__doc__, -"sig=($module, fragment, width, state)\n" +"adpcm2lin($module, fragment, width, state, /)\n" +"--\n" +"\n" "Decode an Intel/DVI ADPCM coded fragment to a linear fragment."); #define AUDIOOP_ADPCM2LIN_METHODDEF \ @@ -833,4 +886,4 @@ return return_value; } -/*[clinic end generated code: output=ee7e58cfd3d0d5a6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=be840bba5d40c2ce input=a9049054013a1b77]*/ diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -3,7 +3,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(binascii_a2b_uu__doc__, -"sig=($module, data)\n" +"a2b_uu($module, data, /)\n" +"--\n" +"\n" "Decode a line of uuencoded data."); #define BINASCII_A2B_UU_METHODDEF \ @@ -33,7 +35,9 @@ } PyDoc_STRVAR(binascii_b2a_uu__doc__, -"sig=($module, data)\n" +"b2a_uu($module, data, /)\n" +"--\n" +"\n" "Uuencode line of data."); #define BINASCII_B2A_UU_METHODDEF \ @@ -63,7 +67,9 @@ } PyDoc_STRVAR(binascii_a2b_base64__doc__, -"sig=($module, data)\n" +"a2b_base64($module, data, /)\n" +"--\n" +"\n" "Decode a line of base64 data."); #define BINASCII_A2B_BASE64_METHODDEF \ @@ -93,7 +99,9 @@ } PyDoc_STRVAR(binascii_b2a_base64__doc__, -"sig=($module, data)\n" +"b2a_base64($module, data, /)\n" +"--\n" +"\n" "Base64-code line of data."); #define BINASCII_B2A_BASE64_METHODDEF \ @@ -123,7 +131,9 @@ } PyDoc_STRVAR(binascii_a2b_hqx__doc__, -"sig=($module, data)\n" +"a2b_hqx($module, data, /)\n" +"--\n" +"\n" "Decode .hqx coding."); #define BINASCII_A2B_HQX_METHODDEF \ @@ -153,7 +163,9 @@ } PyDoc_STRVAR(binascii_rlecode_hqx__doc__, -"sig=($module, data)\n" +"rlecode_hqx($module, data, /)\n" +"--\n" +"\n" "Binhex RLE-code binary data."); #define BINASCII_RLECODE_HQX_METHODDEF \ @@ -183,7 +195,9 @@ } PyDoc_STRVAR(binascii_b2a_hqx__doc__, -"sig=($module, data)\n" +"b2a_hqx($module, data, /)\n" +"--\n" +"\n" "Encode .hqx data."); #define BINASCII_B2A_HQX_METHODDEF \ @@ -213,7 +227,9 @@ } PyDoc_STRVAR(binascii_rledecode_hqx__doc__, -"sig=($module, data)\n" +"rledecode_hqx($module, data, /)\n" +"--\n" +"\n" "Decode hexbin RLE-coded string."); #define BINASCII_RLEDECODE_HQX_METHODDEF \ @@ -243,7 +259,9 @@ } PyDoc_STRVAR(binascii_crc_hqx__doc__, -"sig=($module, data, crc)\n" +"crc_hqx($module, data, crc, /)\n" +"--\n" +"\n" "Compute hqx CRC incrementally."); #define BINASCII_CRC_HQX_METHODDEF \ @@ -278,7 +296,9 @@ } PyDoc_STRVAR(binascii_crc32__doc__, -"sig=($module, data, crc=0)\n" +"crc32($module, data, crc=0, /)\n" +"--\n" +"\n" "Compute CRC-32 incrementally."); #define BINASCII_CRC32_METHODDEF \ @@ -313,7 +333,9 @@ } PyDoc_STRVAR(binascii_b2a_hex__doc__, -"sig=($module, data)\n" +"b2a_hex($module, data, /)\n" +"--\n" +"\n" "Hexadecimal representation of binary data.\n" "\n" "The return value is a bytes object. This function is also\n" @@ -346,7 +368,9 @@ } PyDoc_STRVAR(binascii_a2b_hex__doc__, -"sig=($module, hexstr)\n" +"a2b_hex($module, hexstr, /)\n" +"--\n" +"\n" "Binary data of hexadecimal representation.\n" "\n" "hexstr must contain an even number of hex digits (upper or lower case).\n" @@ -379,7 +403,9 @@ } PyDoc_STRVAR(binascii_a2b_qp__doc__, -"sig=($module, data, header=False)\n" +"a2b_qp($module, /, data, header=False)\n" +"--\n" +"\n" "Decode a string of qp-encoded data."); #define BINASCII_A2B_QP_METHODDEF \ @@ -411,7 +437,9 @@ } PyDoc_STRVAR(binascii_b2a_qp__doc__, -"sig=($module, data, quotetabs=False, istext=True, header=False)\n" +"b2a_qp($module, /, data, quotetabs=False, istext=True, header=False)\n" +"--\n" +"\n" "Encode a string using quoted-printable encoding.\n" "\n" "On encoding, when istext is set, newlines are not encoded, and white\n" @@ -447,4 +475,4 @@ return return_value; } -/*[clinic end generated code: output=831a8ccc9f984001 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=68e2bcc6956b6213 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -3,7 +3,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(zlib_compress__doc__, -"sig=($module, bytes, level=Z_DEFAULT_COMPRESSION)\n" +"compress($module, bytes, level=Z_DEFAULT_COMPRESSION, /)\n" +"--\n" +"\n" "Returns a bytes object containing compressed data.\n" "\n" " bytes\n" @@ -39,7 +41,9 @@ } PyDoc_STRVAR(zlib_decompress__doc__, -"sig=($module, data, wbits=MAX_WBITS, bufsize=DEF_BUF_SIZE)\n" +"decompress($module, data, wbits=MAX_WBITS, bufsize=DEF_BUF_SIZE, /)\n" +"--\n" +"\n" "Returns a bytes object containing the uncompressed data.\n" "\n" " data\n" @@ -78,7 +82,11 @@ } PyDoc_STRVAR(zlib_compressobj__doc__, -"sig=($module, level=Z_DEFAULT_COMPRESSION, method=DEFLATED, wbits=MAX_WBITS, memLevel=DEF_MEM_LEVEL, strategy=Z_DEFAULT_STRATEGY, zdict=None)\n" +"compressobj($module, /, level=Z_DEFAULT_COMPRESSION, method=DEFLATED,\n" +" wbits=MAX_WBITS, memLevel=DEF_MEM_LEVEL,\n" +" strategy=Z_DEFAULT_STRATEGY, zdict=None)\n" +"--\n" +"\n" "Return a compressor object.\n" "\n" " level\n" @@ -132,7 +140,9 @@ } PyDoc_STRVAR(zlib_decompressobj__doc__, -"sig=($module, wbits=MAX_WBITS, zdict=b\'\')\n" +"decompressobj($module, /, wbits=MAX_WBITS, zdict=b\'\')\n" +"--\n" +"\n" "Return a decompressor object.\n" "\n" " wbits\n" @@ -166,7 +176,9 @@ } PyDoc_STRVAR(zlib_Compress_compress__doc__, -"sig=($self, data)\n" +"compress($self, data, /)\n" +"--\n" +"\n" "Returns a bytes object containing compressed data.\n" "\n" " data\n" @@ -203,7 +215,9 @@ } PyDoc_STRVAR(zlib_Decompress_decompress__doc__, -"sig=($self, data, max_length=0)\n" +"decompress($self, data, max_length=0, /)\n" +"--\n" +"\n" "Return a bytes object containing the decompressed version of the data.\n" "\n" " data\n" @@ -245,7 +259,9 @@ } PyDoc_STRVAR(zlib_Compress_flush__doc__, -"sig=($self, mode=zlib.Z_FINISH)\n" +"flush($self, mode=zlib.Z_FINISH, /)\n" +"--\n" +"\n" "Return a bytes object containing any remaining compressed data.\n" "\n" " mode\n" @@ -279,7 +295,9 @@ #if defined(HAVE_ZLIB_COPY) PyDoc_STRVAR(zlib_Compress_copy__doc__, -"sig=($self)\n" +"copy($self, /)\n" +"--\n" +"\n" "Return a copy of the compression object."); #define ZLIB_COMPRESS_COPY_METHODDEF \ @@ -303,7 +321,9 @@ #if defined(HAVE_ZLIB_COPY) PyDoc_STRVAR(zlib_Decompress_copy__doc__, -"sig=($self)\n" +"copy($self, /)\n" +"--\n" +"\n" "Return a copy of the decompression object."); #define ZLIB_DECOMPRESS_COPY_METHODDEF \ @@ -325,7 +345,9 @@ #endif /* !defined(ZLIB_DECOMPRESS_COPY_METHODDEF) */ PyDoc_STRVAR(zlib_Decompress_flush__doc__, -"sig=($self, length=zlib.DEF_BUF_SIZE)\n" +"flush($self, length=zlib.DEF_BUF_SIZE, /)\n" +"--\n" +"\n" "Return a bytes object containing any remaining decompressed data.\n" "\n" " length\n" @@ -354,7 +376,9 @@ } PyDoc_STRVAR(zlib_adler32__doc__, -"sig=($module, data, value=1)\n" +"adler32($module, data, value=1, /)\n" +"--\n" +"\n" "Compute an Adler-32 checksum of data.\n" "\n" " value\n" @@ -390,7 +414,9 @@ } PyDoc_STRVAR(zlib_crc32__doc__, -"sig=($module, data, value=0)\n" +"crc32($module, data, value=0, /)\n" +"--\n" +"\n" "Compute a CRC-32 checksum of data.\n" "\n" " value\n" @@ -424,4 +450,4 @@ return return_value; } -/*[clinic end generated code: output=67d3e81eafcfb982 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bc9473721ca7c962 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2435,7 +2435,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(os_stat__doc__, -"sig=($module, path, *, dir_fd=None, follow_symlinks=True)\n" +"stat($module, /, path, *, dir_fd=None, follow_symlinks=True)\n" +"--\n" +"\n" "Perform a stat system call on the given path.\n" "\n" " path\n" @@ -2486,7 +2488,7 @@ static PyObject * os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=33b6ee92cd1b98de input=5ae155bd475fd20a]*/ +/*[clinic end generated code: output=f1dcaa5e24db9882 input=5ae155bd475fd20a]*/ { return posix_do_stat("stat", path, dir_fd, follow_symlinks); } @@ -2567,7 +2569,10 @@ [clinic start generated code]*/ PyDoc_STRVAR(os_access__doc__, -"sig=($module, path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True)\n" +"access($module, /, path, mode, *, dir_fd=None, effective_ids=False,\n" +" follow_symlinks=True)\n" +"--\n" +"\n" "Use the real uid/gid to test for access to a path.\n" "\n" " path\n" @@ -2627,7 +2632,7 @@ static PyObject * os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks) -/*[clinic end generated code: output=33b3fafc61e778e1 input=2e2e7594371f5b7e]*/ +/*[clinic end generated code: output=a6ed4f151be9df0f input=2e2e7594371f5b7e]*/ { PyObject *return_value = NULL; @@ -2723,7 +2728,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(os_ttyname__doc__, -"sig=($module, fd)\n" +"ttyname($module, fd, /)\n" +"--\n" +"\n" "Return the name of the terminal device connected to \'fd\'.\n" "\n" " fd\n" @@ -2757,7 +2764,7 @@ static char * os_ttyname_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=c3083e665d4d11b9 input=5f72ca83e76b3b45]*/ +/*[clinic end generated code: output=cee7bc4cffec01a2 input=5f72ca83e76b3b45]*/ { char *ret; diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -129,7 +129,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(unicodedata_UCD_decimal__doc__, -"sig=($self, unichr, default=None)\n" +"decimal($self, unichr, default=None, /)\n" +"--\n" +"\n" "Converts a Unicode character into its equivalent decimal value.\n" "\n" "Returns the decimal value assigned to the Unicode character unichr\n" @@ -161,7 +163,7 @@ static PyObject * unicodedata_UCD_decimal_impl(PreviousDBVersion *self, PyUnicodeObject *unichr, PyObject *default_value) -/*[clinic end generated code: output=a3ad5de9393acb2f input=c25c9d2b4de076b1]*/ +/*[clinic end generated code: output=8689669896d293df input=c25c9d2b4de076b1]*/ { int have_old = 0; long rc; diff --git a/Objects/descrobject.c b/Objects/descrobject.c --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -353,13 +353,13 @@ static PyObject * method_get_doc(PyMethodDescrObject *descr, void *closure) { - return _PyType_GetDocFromInternalDoc(descr->d_method->ml_doc); + return _PyType_GetDocFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc); } static PyObject * method_get_text_signature(PyMethodDescrObject *descr, void *closure) { - return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_doc); + return _PyType_GetTextSignatureFromInternalDoc(descr->d_method->ml_name, descr->d_method->ml_doc); } static PyObject * @@ -466,13 +466,13 @@ static PyObject * wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure) { - return _PyType_GetDocFromInternalDoc(descr->d_base->doc); + return _PyType_GetDocFromInternalDoc(descr->d_base->name, descr->d_base->doc); } static PyObject * wrapperdescr_get_text_signature(PyWrapperDescrObject *descr, void *closure) { - return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->doc); + return _PyType_GetTextSignatureFromInternalDoc(descr->d_base->name, descr->d_base->doc); } static PyGetSetDef wrapperdescr_getset[] = { @@ -1151,13 +1151,13 @@ static PyObject * wrapper_doc(wrapperobject *wp, void *closure) { - return _PyType_GetDocFromInternalDoc(wp->descr->d_base->doc); + return _PyType_GetDocFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc); } static PyObject * wrapper_text_signature(wrapperobject *wp, void *closure) { - return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->doc); + return _PyType_GetTextSignatureFromInternalDoc(wp->descr->d_base->name, wp->descr->d_base->doc); } static PyObject * diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1702,7 +1702,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(dict_fromkeys__doc__, -"sig=($type, iterable, value=None)\n" +"fromkeys($type, iterable, value=None, /)\n" +"--\n" +"\n" "Returns a new dict with keys from iterable and values equal to value."); #define DICT_FROMKEYS_METHODDEF \ @@ -1730,7 +1732,7 @@ static PyObject * dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value) -/*[clinic end generated code: output=aff6e583703dbeba input=b85a667f9bf4669d]*/ +/*[clinic end generated code: output=55f8dc0ffa87406f input=b85a667f9bf4669d]*/ { PyObject *it; /* iter(seq) */ PyObject *key; @@ -2209,7 +2211,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(dict___contains____doc__, -"sig=($self, key)\n" +"__contains__($self, key, /)\n" +"--\n" +"\n" "True if D has a key k, else False."); #define DICT___CONTAINS___METHODDEF \ @@ -2217,7 +2221,7 @@ static PyObject * dict___contains__(PyDictObject *self, PyObject *key) -/*[clinic end generated code: output=c654684a6d880281 input=b852b2a19b51ab24]*/ +/*[clinic end generated code: output=3cf3f8aaf2cc5cc3 input=b852b2a19b51ab24]*/ { register PyDictObject *mp = self; Py_hash_t hash; diff --git a/Objects/methodobject.c b/Objects/methodobject.c --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -182,13 +182,13 @@ static PyObject * meth_get__text_signature__(PyCFunctionObject *m, void *closure) { - return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_doc); + return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc); } static PyObject * meth_get__doc__(PyCFunctionObject *m, void *closure) { - return _PyType_GetDocFromInternalDoc(m->m_ml->ml_doc); + return _PyType_GetDocFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc); } static PyObject * diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -55,51 +55,75 @@ slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds); /* - * finds the docstring's introspection signature. + * finds the beginning of the docstring's introspection signature. * if present, returns a pointer pointing to the first '('. * otherwise returns NULL. + * + * doesn't guarantee that the signature is valid, only that it + * has a valid prefix. (the signature must also pass skip_signature.) */ static const char * -find_signature(const char *doc) -{ - if (doc && !strncmp(doc, "sig=(", 5)) - return doc + 4; - return NULL; -} - +find_signature(const char *name, const char *doc) +{ + const char *dot; + size_t length; + + if (!doc) + return NULL; + + assert(name != NULL); + + /* for dotted names like classes, only use the last component */ + dot = strrchr(name, '.'); + if (dot) + name = dot + 1; + + length = strlen(name); + if (strncmp(doc, name, length)) + return NULL; + doc += length; + if (*doc != '(') + return NULL; + return doc; +} + +#define SIGNATURE_END_MARKER ")\n--\n\n" +#define SIGNATURE_END_MARKER_LENGTH 6 /* - * skips to the end of the docstring's instrospection signature. + * skips past the end of the docstring's instrospection signature. + * (assumes doc starts with a valid signature prefix.) */ static const char * skip_signature(const char *doc) { - while (*doc && *doc != '\n') + while (*doc) { + if ((*doc == *SIGNATURE_END_MARKER) && + !strncmp(doc, SIGNATURE_END_MARKER, SIGNATURE_END_MARKER_LENGTH)) + return doc + SIGNATURE_END_MARKER_LENGTH; + if ((*doc == '\n') && (doc[1] == '\n')) + return NULL; doc++; - return doc; + } + return NULL; } static const char * -skip_eols(const char *trace) -{ - while (*trace == '\n') - trace++; - return trace; -} - -static const char * -_PyType_DocWithoutSignature(const char *internal_doc) -{ - const char *signature = find_signature(internal_doc); - - if (signature) - return skip_eols(skip_signature(signature)); +_PyType_DocWithoutSignature(const char *name, const char *internal_doc) +{ + const char *doc = find_signature(name, internal_doc); + + if (doc) { + doc = skip_signature(doc); + if (doc) + return doc; + } return internal_doc; } PyObject * -_PyType_GetDocFromInternalDoc(const char *internal_doc) -{ - const char *doc = _PyType_DocWithoutSignature(internal_doc); +_PyType_GetDocFromInternalDoc(const char *name, const char *internal_doc) +{ + const char *doc = _PyType_DocWithoutSignature(name, internal_doc); if (!doc) { Py_INCREF(Py_None); @@ -110,18 +134,26 @@ } PyObject * -_PyType_GetTextSignatureFromInternalDoc(const char *internal_doc) -{ - const char *signature = find_signature(internal_doc); - const char *doc; - - if (!signature) { +_PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_doc) +{ + const char *start = find_signature(name, internal_doc); + const char *end; + + if (start) + end = skip_signature(start); + else + end = NULL; + if (!end) { Py_INCREF(Py_None); return Py_None; } - doc = skip_signature(signature); - return PyUnicode_FromStringAndSize(signature, doc - signature); + /* back "end" up until it points just past the final ')' */ + end -= SIGNATURE_END_MARKER_LENGTH - 1; + assert((end - start) >= 2); /* should be "()" at least */ + assert(end[-1] == ')'); + assert(end[0] == '\n'); + return PyUnicode_FromStringAndSize(start, end - start); } unsigned int @@ -699,7 +731,7 @@ { PyObject *result; if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) && type->tp_doc != NULL) { - return _PyType_GetDocFromInternalDoc(type->tp_doc); + return _PyType_GetDocFromInternalDoc(type->tp_name, type->tp_doc); } result = _PyDict_GetItemId(type->tp_dict, &PyId___doc__); if (result == NULL) { @@ -719,7 +751,7 @@ static PyObject * type_get_text_signature(PyTypeObject *type, void *context) { - return _PyType_GetTextSignatureFromInternalDoc(type->tp_doc); + return _PyType_GetTextSignatureFromInternalDoc(type->tp_name, type->tp_doc); } static int @@ -2597,7 +2629,7 @@ /* need to make a copy of the docstring slot, which usually points to a static string literal */ if (slot->slot == Py_tp_doc) { - const char *old_doc = _PyType_DocWithoutSignature(slot->pfunc); + const char *old_doc = _PyType_DocWithoutSignature(type->tp_name, slot->pfunc); size_t len = strlen(old_doc)+1; char *tp_doc = PyObject_MALLOC(len); if (tp_doc == NULL) { @@ -3002,7 +3034,7 @@ PyDoc_STRVAR(type_doc, /* this text signature cannot be accurate yet. will fix. --larry */ -"sig=(object_or_name, bases, dict)\n" +"type(object_or_name, bases, dict)\n" "type(object) -> the object's type\n" "type(name, bases, dict) -> a new type"); @@ -4198,7 +4230,7 @@ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - PyDoc_STR("sig=()\nThe most base type"), /* tp_doc */ + PyDoc_STR("object()\n--\n\nThe most base type"), /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ object_richcompare, /* tp_richcompare */ @@ -4665,7 +4697,8 @@ */ if (_PyDict_GetItemId(type->tp_dict, &PyId___doc__) == NULL) { if (type->tp_doc != NULL) { - const char *old_doc = _PyType_DocWithoutSignature(type->tp_doc); + const char *old_doc = _PyType_DocWithoutSignature(type->tp_name, + type->tp_doc); PyObject *doc = PyUnicode_FromString(old_doc); if (doc == NULL) goto error; @@ -5327,7 +5360,7 @@ static struct PyMethodDef tp_new_methoddef[] = { {"__new__", (PyCFunction)tp_new_wrapper, METH_VARARGS|METH_KEYWORDS, - PyDoc_STR("sig=($type, *args, **kwargs)\n" + PyDoc_STR("__new__($type, *args, **kwargs)\n--\n\n" "Create and return a new object. " "See help(type) for accurate signature.")}, {0} @@ -6101,22 +6134,22 @@ ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, DOC) #define UNSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \ - "sig=($self)\n" DOC) + NAME "($self)\n--\n\n" DOC) #define IBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \ - "sig=($self, value)\nReturn self" DOC "value.") + NAME "($self, value)\n--\n\nReturn self" DOC "value.") #define BINSLOT(NAME, SLOT, FUNCTION, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \ - "sig=($self, value)\nReturn self" DOC "value.") + NAME "($self, value)\n--\n\nReturn self" DOC "value.") #define RBINSLOT(NAME, SLOT, FUNCTION, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \ - "sig=($self, value)\nReturn value" DOC "self.") + NAME "($self, value)\n--\n\nReturn value" DOC "self.") #define BINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \ - "sig=($self, value)\n" DOC) + NAME "($self, value)\n--\n\n" DOC) #define RBINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \ - "sig=($self, value)\n" DOC) + NAME "($self, value)\n--\n\n" DOC) static slotdef slotdefs[] = { TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""), @@ -6124,51 +6157,51 @@ TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""), TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""), TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc, - "sig=($self)\nReturn repr(self)."), + "__repr__($self)\n--\n\nReturn repr(self)."), TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc, - "sig=($self)\nReturn hash(self)."), + "__hash__($self)\n--\n\nReturn hash(self)."), FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call, - "sig=($self, *args, **kwargs)\nCall self as a function.", + "__call__($self, *args, **kwargs)\n--\n\nCall self as a function.", PyWrapperFlag_KEYWORDS), TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc, - "sig=($self)\nReturn str(self)."), + "__str__($self)\n--\n\nReturn str(self)."), TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook, wrap_binaryfunc, - "sig=($self, name)\nReturn getattr(self, name)."), + "__getattribute__($self, name)\n--\n\nReturn getattr(self, name)."), TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""), TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr, - "sig=($self, name, value)\nImplement setattr(self, name, value)."), + "__setattr__($self, name, value)\n--\n\nImplement setattr(self, name, value)."), TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr, - "sig=($self, name)\nImplement delattr(self, name)."), + "__delattr__($self, name)\n--\n\nImplement delattr(self, name)."), TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt, - "sig=($self, value)\nReturn selfvalue."), + "__gt__($self, value)\n--\n\nReturn self>value."), TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge, - "sig=($self, value)\nReturn self>=value."), + "__ge__=($self, value)\n--\n\nReturn self>=value."), TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc, - "sig=($self)\nImplement iter(self)."), + "__iter__($self)\n--\n\nImplement iter(self)."), TPSLOT("__next__", tp_iternext, slot_tp_iternext, wrap_next, - "sig=($self)\nImplement next(self)."), + "__next__($self)\n--\n\nImplement next(self)."), TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get, - "sig=($self, instance, owner)\nReturn an attribute of instance, which is of type owner."), + "__get__($self, instance, owner)\n--\n\nReturn an attribute of instance, which is of type owner."), TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set, - "sig=($self, instance, value)\nSet an attribute of instance to value."), + "__set__($self, instance, value)\n--\n\nSet an attribute of instance to value."), TPSLOT("__delete__", tp_descr_set, slot_tp_descr_set, wrap_descr_delete, - "sig=(instance)\nDelete an attribute of instance."), + "__delete__(instance)\n--\n\nDelete an attribute of instance."), FLSLOT("__init__", tp_init, slot_tp_init, (wrapperfunc)wrap_init, - "sig=($self, *args, **kwargs)\n" + "__init__($self, *args, **kwargs)\n--\n\n" "Initialize self. See help(type(self)) for accurate signature.", PyWrapperFlag_KEYWORDS), TPSLOT("__new__", tp_new, slot_tp_new, NULL, - "sig=(type, *args, **kwargs)\n" + "__new__(type, *args, **kwargs)\n--\n\n" "Create and return new object. See help(type) for accurate signature."), TPSLOT("__del__", tp_finalize, slot_tp_finalize, (wrapperfunc)wrap_del, ""), @@ -6193,9 +6226,9 @@ RBINSLOTNOTINFIX("__rdivmod__", nb_divmod, slot_nb_divmod, "Return divmod(value, self)."), NBSLOT("__pow__", nb_power, slot_nb_power, wrap_ternaryfunc, - "sig=($self, value, mod=None)\nReturn pow(self, value, mod)."), + "__pow__($self, value, mod=None)\n--\n\nReturn pow(self, value, mod)."), NBSLOT("__rpow__", nb_power, slot_nb_power, wrap_ternaryfunc_r, - "sig=($self, value, mod=None)\nReturn pow(value, self, mod)."), + "__rpow__($self, value, mod=None)\n--\n\nReturn pow(value, self, mod)."), UNSLOT("__neg__", nb_negative, slot_nb_negative, wrap_unaryfunc, "-self"), UNSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc, "+self"), UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc, @@ -6246,48 +6279,48 @@ IBSLOT("__itruediv__", nb_inplace_true_divide, slot_nb_inplace_true_divide, wrap_binaryfunc, "/"), NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc, - "sig=($self)\n" + "__index__($self)\n--\n\n" "Return self converted to an integer, if self is suitable" "for use as an index into a list."), MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc, - "sig=($self)\nReturn len(self)."), + "__len__($self)\n--\n\nReturn len(self)."), MPSLOT("__getitem__", mp_subscript, slot_mp_subscript, wrap_binaryfunc, - "sig=($self, key)\nReturn self[key]."), + "__getitem__($self, key)\n--\n\nReturn self[key]."), MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript, wrap_objobjargproc, - "sig=($self, key, value)\nSet self[key] to value."), + "__setitem__($self, key, value)\n--\n\nSet self[key] to value."), MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript, wrap_delitem, - "sig=(key)\nDelete self[key]."), + "__delitem__(key)\n--\n\nDelete self[key]."), SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc, - "sig=($self)\nReturn len(self)."), + "__len__($self)\n--\n\nReturn len(self)."), /* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL. The logic in abstract.c always falls back to nb_add/nb_multiply in this case. Defining both the nb_* and the sq_* slots to call the user-defined methods has unexpected side-effects, as shown by test_descr.notimplemented() */ SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc, - "sig=($self, value)\nReturn self+value."), + "__add__($self, value)\n--\n\nReturn self+value."), SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, - "sig=($self, value)\nReturn self*value.n"), + "__mul__($self, value)\n--\n\nReturn self*value.n"), SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, - "sig=($self, value)\nReturn self*value."), + "__rmul__($self, value)\n--\n\nReturn self*value."), SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, - "sig=($self, key)\nReturn self[key]."), + "__getitem__($self, key)\n--\n\nReturn self[key]."), SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem, - "sig=($self, key, value)\nSet self[key] to value."), + "__setitem__($self, key, value)\n--\n\nSet self[key] to value."), SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem, - "sig=($self, key)\nDelete self[key]."), + "__delitem__($self, key)\n--\n\nDelete self[key]."), SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc, - "sig=($self, key)\nReturn key in self."), + "__contains__($self, key)\n--\n\nReturn key in self."), SQSLOT("__iadd__", sq_inplace_concat, NULL, wrap_binaryfunc, - "sig=($self, value)\nImplement self+=value."), + "__iadd__($self, value)\n--\n\nImplement self+=value."), SQSLOT("__imul__", sq_inplace_repeat, NULL, wrap_indexargfunc, - "sig=($self, value)\nImplement self*=value."), + "__imul__($self, value)\n--\n\nImplement self*=value."), {NULL} }; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -12893,7 +12893,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(unicode_maketrans__doc__, -"sig=(x, y=None, z=None)\n" +"maketrans(x, y=None, z=None, /)\n" +"--\n" +"\n" "Return a translation table usable for str.translate().\n" "\n" "If there is only one argument, it must be a dictionary mapping Unicode\n" @@ -12930,7 +12932,7 @@ static PyObject * unicode_maketrans_impl(PyObject *x, PyObject *y, PyObject *z) -/*[clinic end generated code: output=ca001ac83ed32269 input=7bfbf529a293c6c5]*/ +/*[clinic end generated code: output=566edf630f77436a input=7bfbf529a293c6c5]*/ { PyObject *new = NULL, *key, *value; Py_ssize_t i = 0; diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -232,7 +232,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_lock_held__doc__, -"sig=($module)\n" +"lock_held($module, /)\n" +"--\n" +"\n" "Return True if the import lock is currently held, else False.\n" "\n" "On platforms without threads, return False."); @@ -251,7 +253,7 @@ static PyObject * _imp_lock_held_impl(PyModuleDef *module) -/*[clinic end generated code: output=5ce46d12a8e4c469 input=9b088f9b217d9bdf]*/ +/*[clinic end generated code: output=dae65674966baa65 input=9b088f9b217d9bdf]*/ { #ifdef WITH_THREAD return PyBool_FromLong(import_lock_thread != -1); @@ -270,7 +272,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_acquire_lock__doc__, -"sig=($module)\n" +"acquire_lock($module, /)\n" +"--\n" +"\n" "Acquires the interpreter\'s import lock for the current thread.\n" "\n" "This lock should be used by import hooks to ensure thread-safety when importing\n" @@ -290,7 +294,7 @@ static PyObject * _imp_acquire_lock_impl(PyModuleDef *module) -/*[clinic end generated code: output=b0dd6a132ad25961 input=4a2d4381866d5fdc]*/ +/*[clinic end generated code: output=478f1fa089fdb9a4 input=4a2d4381866d5fdc]*/ { #ifdef WITH_THREAD _PyImport_AcquireLock(); @@ -308,7 +312,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_release_lock__doc__, -"sig=($module)\n" +"release_lock($module, /)\n" +"--\n" +"\n" "Release the interpreter\'s import lock.\n" "\n" "On platforms without threads, this function does nothing."); @@ -327,7 +333,7 @@ static PyObject * _imp_release_lock_impl(PyModuleDef *module) -/*[clinic end generated code: output=b1e6e9d723cf5f89 input=934fb11516dd778b]*/ +/*[clinic end generated code: output=36c77a6832fdafd4 input=934fb11516dd778b]*/ { #ifdef WITH_THREAD if (_PyImport_ReleaseLock() < 0) { @@ -927,7 +933,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp__fix_co_filename__doc__, -"sig=($module, code, path)\n" +"_fix_co_filename($module, code, path, /)\n" +"--\n" +"\n" "Changes code.co_filename to specify the passed-in file path.\n" "\n" " code\n" @@ -960,7 +968,7 @@ static PyObject * _imp__fix_co_filename_impl(PyModuleDef *module, PyCodeObject *code, PyObject *path) -/*[clinic end generated code: output=3fe5b5a1b0d497df input=895ba50e78b82f05]*/ +/*[clinic end generated code: output=6b4b1edeb0d55c5d input=895ba50e78b82f05]*/ { update_compiled_module(code, path); @@ -1823,7 +1831,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_extension_suffixes__doc__, -"sig=($module)\n" +"extension_suffixes($module, /)\n" +"--\n" +"\n" "Returns the list of file suffixes used to identify extension modules."); #define _IMP_EXTENSION_SUFFIXES_METHODDEF \ @@ -1840,7 +1850,7 @@ static PyObject * _imp_extension_suffixes_impl(PyModuleDef *module) -/*[clinic end generated code: output=c1bcfbddabefa00a input=ecdeeecfcb6f839e]*/ +/*[clinic end generated code: output=bb30a2438167798c input=ecdeeecfcb6f839e]*/ { PyObject *list; const char *suffix; @@ -1878,7 +1888,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_init_builtin__doc__, -"sig=($module, name)\n" +"init_builtin($module, name, /)\n" +"--\n" +"\n" "Initializes a built-in module."); #define _IMP_INIT_BUILTIN_METHODDEF \ @@ -1905,7 +1917,7 @@ static PyObject * _imp_init_builtin_impl(PyModuleDef *module, PyObject *name) -/*[clinic end generated code: output=02437efd4668f53e input=f934d2231ec52a2e]*/ +/*[clinic end generated code: output=a0244948a43f8e26 input=f934d2231ec52a2e]*/ { int ret; PyObject *m; @@ -1932,7 +1944,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_init_frozen__doc__, -"sig=($module, name)\n" +"init_frozen($module, name, /)\n" +"--\n" +"\n" "Initializes a frozen module."); #define _IMP_INIT_FROZEN_METHODDEF \ @@ -1959,7 +1973,7 @@ static PyObject * _imp_init_frozen_impl(PyModuleDef *module, PyObject *name) -/*[clinic end generated code: output=20cea421af513afe input=13019adfc04f3fb3]*/ +/*[clinic end generated code: output=e4bc2bff296f8f22 input=13019adfc04f3fb3]*/ { int ret; PyObject *m; @@ -1986,7 +2000,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_get_frozen_object__doc__, -"sig=($module, name)\n" +"get_frozen_object($module, name, /)\n" +"--\n" +"\n" "Create a code object for a frozen module."); #define _IMP_GET_FROZEN_OBJECT_METHODDEF \ @@ -2013,7 +2029,7 @@ static PyObject * _imp_get_frozen_object_impl(PyModuleDef *module, PyObject *name) -/*[clinic end generated code: output=f00d01ae30ec842f input=ed689bc05358fdbd]*/ +/*[clinic end generated code: output=4089ec702a9d70c5 input=ed689bc05358fdbd]*/ { return get_frozen_object(name); } @@ -2028,7 +2044,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_is_frozen_package__doc__, -"sig=($module, name)\n" +"is_frozen_package($module, name, /)\n" +"--\n" +"\n" "Returns True if the module name is of a frozen package."); #define _IMP_IS_FROZEN_PACKAGE_METHODDEF \ @@ -2055,7 +2073,7 @@ static PyObject * _imp_is_frozen_package_impl(PyModuleDef *module, PyObject *name) -/*[clinic end generated code: output=35c78f2448c6fcff input=81b6cdecd080fbb8]*/ +/*[clinic end generated code: output=86aab14dcd4b959b input=81b6cdecd080fbb8]*/ { return is_frozen_package(name); } @@ -2070,7 +2088,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_is_builtin__doc__, -"sig=($module, name)\n" +"is_builtin($module, name, /)\n" +"--\n" +"\n" "Returns True if the module name corresponds to a built-in module."); #define _IMP_IS_BUILTIN_METHODDEF \ @@ -2097,7 +2117,7 @@ static PyObject * _imp_is_builtin_impl(PyModuleDef *module, PyObject *name) -/*[clinic end generated code: output=641689f833347f66 input=86befdac021dd1c7]*/ +/*[clinic end generated code: output=d5847f8cac50946e input=86befdac021dd1c7]*/ { return PyLong_FromLong(is_builtin(name)); } @@ -2112,7 +2132,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_is_frozen__doc__, -"sig=($module, name)\n" +"is_frozen($module, name, /)\n" +"--\n" +"\n" "Returns True if the module name corresponds to a frozen module."); #define _IMP_IS_FROZEN_METHODDEF \ @@ -2139,7 +2161,7 @@ static PyObject * _imp_is_frozen_impl(PyModuleDef *module, PyObject *name) -/*[clinic end generated code: output=0f80c7a3f283a686 input=7301dbca1897d66b]*/ +/*[clinic end generated code: output=6691af884ba4987d input=7301dbca1897d66b]*/ { const struct _frozen *p; @@ -2161,7 +2183,9 @@ [clinic start generated code]*/ PyDoc_STRVAR(_imp_load_dynamic__doc__, -"sig=($module, name, path, file=None)\n" +"load_dynamic($module, name, path, file=None, /)\n" +"--\n" +"\n" "Loads an extension module."); #define _IMP_LOAD_DYNAMIC_METHODDEF \ @@ -2190,7 +2214,7 @@ static PyObject * _imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, PyObject *file) -/*[clinic end generated code: output=8f33f48dc6252948 input=af64f06e4bad3526]*/ +/*[clinic end generated code: output=81d11a1fbd1ea0a8 input=af64f06e4bad3526]*/ { PyObject *mod; FILE *fp; diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -1123,10 +1123,12 @@ sys.stdout = saved_stdout -def create_regex(before, after, word=True): +def create_regex(before, after, word=True, whole_line=True): """Create an re object for matching marker lines.""" group_re = "\w+" if word else ".+" - pattern = r'^{}({}){}$' + pattern = r'{}({}){}' + if whole_line: + pattern = '^' + pattern + '$' pattern = pattern.format(re.escape(before), group_re, re.escape(after)) return re.compile(pattern) @@ -1218,6 +1220,7 @@ self.language = language before, _, after = language.start_line.partition('{dsl_name}') assert _ == '{dsl_name}' + self.find_start_re = create_regex(before, after, whole_line=False) self.start_re = create_regex(before, after) self.verify = verify self.last_checksum_re = None @@ -1735,11 +1738,15 @@ except KeyError: fail("Can't identify file type for file " + repr(filename)) - clinic = Clinic(language, force=force, verify=verify, filename=filename) - with open(filename, 'r', encoding=encoding) as f: raw = f.read() + # exit quickly if there are no clinic markers in the file + find_start_re = BlockParser("", language).find_start_re + if not find_start_re.search(raw): + return + + clinic = Clinic(language, force=force, verify=verify, filename=filename) cooked = clinic.parse(raw) if (cooked == raw) and not force: return @@ -1897,7 +1904,7 @@ full_name=None, return_converter, return_annotation=_empty, docstring=None, kind=CALLABLE, coexist=False, - suppress_signature=False): + docstring_only=False): self.parameters = parameters or collections.OrderedDict() self.return_annotation = return_annotation self.name = name @@ -1911,7 +1918,11 @@ self.kind = kind self.coexist = coexist self.self_converter = None - self.suppress_signature = suppress_signature + # docstring_only means "don't generate a machine-readable + # signature, just a normal docstring". it's True for + # functions with optional groups because we can't represent + # those accurately with inspect.Signature in 3.4. + self.docstring_only = docstring_only self.rendered_parameters = None @@ -1951,7 +1962,7 @@ 'full_name': self.full_name, 'return_converter': self.return_converter, 'return_annotation': self.return_annotation, 'docstring': self.docstring, 'kind': self.kind, 'coexist': self.coexist, - 'suppress_signature': self.suppress_signature, + 'docstring_only': self.docstring_only, } kwargs.update(overrides) f = Function(**kwargs) @@ -1987,6 +1998,9 @@ def is_keyword_only(self): return self.kind == inspect.Parameter.KEYWORD_ONLY + def is_positional_only(self): + return self.kind == inspect.Parameter.POSITIONAL_ONLY + def copy(self, **overrides): kwargs = { 'name': self.name, 'kind': self.kind, 'default':self.default, @@ -2929,7 +2943,7 @@ Returns the length of the line's margin. """ if '\t' in line: - fail('Tab characters are illegal in the Clinic DSL.') + fail('Tab characters are illegal in the Argument Clinic DSL.') stripped = line.lstrip() if not len(stripped): # we can't tell anything from an empty line @@ -3694,7 +3708,7 @@ else: fail("Function " + self.function.name + " has an unsupported group configuration. (Unexpected state " + str(self.parameter_state) + ".b)") self.group += 1 - self.function.suppress_signature = True + self.function.docstring_only = True elif symbol == ']': if not self.group: fail("Function " + self.function.name + " has a ] without a matching [.") @@ -3783,21 +3797,20 @@ # don't render a docstring at all, no signature, nothing. return f.docstring - add, output = text_accumulator() + text, add, output = _text_accumulator() parameters = f.render_parameters ## ## docstring first line ## - if not f.suppress_signature: - add('sig=') + if new_or_init: + # classes get *just* the name of the class + # not __new__, not __init__, and not module.classname + assert f.cls + add(f.cls.name) else: - if new_or_init: - assert f.cls - add(f.cls.name) - else: - add(f.name) + add(f.name) add('(') # populate "right_bracket_count" field for every parameter @@ -3834,53 +3847,105 @@ right_bracket_count -= 1 return s + need_slash = False + added_slash = False + need_a_trailing_slash = False + + # we only need a trailing slash: + # * if this is not a "docstring_only" signature + # * and if the last *shown* parameter is + # positional only + if not f.docstring_only: + for p in reversed(parameters): + if not p.converter.show_in_signature: + continue + if p.is_positional_only(): + need_a_trailing_slash = True + break + + added_star = False - add_comma = False + + first_parameter = True + last_p = parameters[-1] + line_length = len(''.join(text)) + indent = " " * line_length + def add_parameter(text): + nonlocal line_length + nonlocal first_parameter + if first_parameter: + s = text + first_parameter = False + else: + s = ' ' + text + if line_length + len(s) >= 72: + add('\n') + add(indent) + line_length = len(indent) + s = text + line_length += len(s) + add(s) for p in parameters: if not p.converter.show_in_signature: continue - assert p.name + is_self = isinstance(p.converter, self_converter) + if is_self and f.docstring_only: + # this isn't a real machine-parsable signature, + # so let's not print the "self" parameter + continue + + if p.is_positional_only(): + need_slash = not f.docstring_only + elif need_slash and not (added_slash or p.is_positional_only()): + added_slash = True + add_parameter('/,') + if p.is_keyword_only() and not added_star: added_star = True - if add_comma: - add(', ') - add('*') - add_comma = True + add_parameter('*,') + + p_add, p_output = text_accumulator() + p_add(fix_right_bracket_count(p.right_bracket_count)) + + if isinstance(p.converter, self_converter): + # annotate first parameter as being a "self". + # + # if inspect.Signature gets this function, + # and it's already bound, the self parameter + # will be stripped off. + # + # if it's not bound, it should be marked + # as positional-only. + # + # note: we don't print "self" for __init__, + # because this isn't actually the signature + # for __init__. (it can't be, __init__ doesn't + # have a docstring.) if this is an __init__ + # (or __new__), then this signature is for + # calling the class to contruct a new instance. + p_add('$') name = p.converter.signature_name or p.name - - a = [] - if isinstance(p.converter, self_converter): - if f.suppress_signature: - continue - else: - # annotate first parameter as being a "self". - # - # if inspect.Signature gets this function, and it's already bound, - # the self parameter will be stripped off. - # - # if it's not bound, it should be marked as positional-only. - a.append('$') - a.append(name) - else: - a.append(name) + p_add(name) + if p.converter.is_optional(): - a.append('=') + p_add('=') value = p.converter.py_default if not value: value = repr(p.converter.default) - a.append(value) - s = fix_right_bracket_count(p.right_bracket_count) - s += "".join(a) - if add_comma: - add(', ') - add(s) - add_comma = True + p_add(value) + + if (p != last_p) or need_a_trailing_slash: + p_add(',') + + add_parameter(p_output()) add(fix_right_bracket_count(0)) + if need_a_trailing_slash: + add_parameter('/') add(')') # PEP 8 says: @@ -3896,6 +3961,9 @@ # add(' -> ') # add(f.return_converter.py_default) + if not f.docstring_only: + add("\n--\n") + docstring_first_line = output() # now fix up the places where the brackets look wrong diff --git a/Tools/clinic/clinic_test.py b/Tools/clinic/clinic_test.py --- a/Tools/clinic/clinic_test.py +++ b/Tools/clinic/clinic_test.py @@ -359,7 +359,9 @@ Perform a stat system call on the given path.""") self.assertEqual(""" -sig=($module, path) +stat($module, /, path) +-- + Perform a stat system call on the given path. path @@ -379,7 +381,9 @@ Okay, we're done here. """) self.assertEqual(""" -sig=($module, x, y) +bar($module, /, x, y) +-- + This is the documentation for foo. x @@ -395,7 +399,7 @@ path: str This/used to break Clinic! """) - self.assertEqual("sig=($module, path)\n\nThis/used to break Clinic!", function.docstring) + self.assertEqual("stat($module, /, path)\n--\n\nThis/used to break Clinic!", function.docstring) def test_c_name(self): function = self.parse_function("module os\nos.stat as os_stat_fn") @@ -504,7 +508,8 @@ self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) self.assertEqual(function.docstring.strip(), """ -imaginary([[y1, y2,] x1, x2,] ch, [attr1, attr2, attr3, [attr4, attr5, attr6]]) +imaginary([[y1, y2,] x1, x2,] ch, [attr1, attr2, attr3, [attr4, attr5, + attr6]]) y1 @@ -624,9 +629,23 @@ Docstring """) - self.assertEqual("sig=($module)\nDocstring", function.docstring) + self.assertEqual("bar($module, /)\n--\n\nDocstring", function.docstring) self.assertEqual(1, len(function.parameters)) # self! + def test_init_with_no_parameters(self): + function = self.parse_function(""" +module foo +class foo.Bar "unused" "notneeded" +foo.Bar.__init__ + +Docstring + +""", signatures_in_block=3, function_index=2) + # self is not in the signature + self.assertEqual("Bar()\n--\n\nDocstring", function.docstring) + # but it *is* a parameter + self.assertEqual(1, len(function.parameters)) + def test_illegal_module_line(self): self.parse_function_should_fail(""" module foo @@ -719,7 +738,9 @@ Not at column 0! """) self.assertEqual(""" -sig=($module, x, *, y) +bar($module, /, x, *, y) +-- + Not at column 0! x @@ -733,7 +754,7 @@ path: str This/used to break Clinic! """) - self.assertEqual("sig=($module, path)\nThis/used to break Clinic!", function.docstring) + self.assertEqual("stat($module, /, path)\n--\n\nThis/used to break Clinic!", function.docstring) def test_directive(self): c = FakeClinic() @@ -756,13 +777,13 @@ parser.parse(block) return block - def parse_function(self, text): + def parse_function(self, text, signatures_in_block=2, function_index=1): block = self.parse(text) s = block.signatures - self.assertEqual(len(s), 2) + self.assertEqual(len(s), signatures_in_block) assert isinstance(s[0], clinic.Module) - assert isinstance(s[1], clinic.Function) - return s[1] + assert isinstance(s[function_index], clinic.Function) + return s[function_index] def test_scaffolding(self): # test repr on special values -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sun Feb 9 08:53:35 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 09 Feb 2014 08:53:35 +0100 Subject: [Python-checkins] Daily reference leaks (9e7594d65178): sum=0 Message-ID: results for 9e7594d65178 on branch "default" -------------------------------------------- test_site leaked [0, -2, 2] references, sum=0 test_site leaked [0, -2, 2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogUNYARh', '-x'] From python-checkins at python.org Sun Feb 9 10:26:31 2014 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Feb 2014 10:26:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Simplify_PEP_101_a_bit=3B_rem?= =?utf-8?q?ove_instructions_for_=22prev=22_directory=2E?= Message-ID: <3fMPyH4byBz7LkF@mail.python.org> http://hg.python.org/peps/rev/74bd49748c0a changeset: 5369:74bd49748c0a user: Georg Brandl date: Sun Feb 09 10:27:17 2014 +0100 summary: Simplify PEP 101 a bit; remove instructions for "prev" directory. files: pep-0101.txt | 74 +++++++++++++++------------------------ 1 files changed, 29 insertions(+), 45 deletions(-) diff --git a/pep-0101.txt b/pep-0101.txt --- a/pep-0101.txt +++ b/pep-0101.txt @@ -380,29 +380,15 @@ ___ Now you need to go to dinsdale.python.org and move all the files in place over there. Our policy is that every Python version gets its own - directory, but each directory may contain several releases. We keep all - old releases, moving them into a "prev" subdirectory when we have a new - release. - - So, there's a directory called "3.2" which contains Python-3.2.msi and - Python-3.2.tgz, along with a "prev" subdirectory containing - Python-3.2a1.msi, Python-3.2a1.tgz, Python-3.2a1.tar.bz2, etc. + directory, but each directory may contain several releases. ___ On dinsdale, cd /data/ftp.python.org/pub/python/X.Y.Z creating it if necessary. Make sure it is owned by group 'webmaster' and group-writable. - ___ Move the previous release files to a directory called 'prev' - creating the directory if necessary (make sure the directory has - g+ws bits on). If this is the first alpha release of a new Python - version, skip this step. - - For pre-releases (alpha, beta, rc), don't move things into a 'prev' - directory, You'll move everything in there when the final release - comes out. - - ___ Move the release .tgz, tar.bz2, .tar.xz, .dmg and .msi files into - place, as well as the .asc GPG signature files. + ___ Move the release .tgz, and .tar.xz files into place, as well as the + .asc GPG signature files. The Win/Mac binaries are usually put there + by the experts themselves. Make sure they are world readable. They should also be group writable, and group-owned by webmaster. @@ -421,9 +407,6 @@ If it is a release of a security-fix-only version, tell the DE to build a version with the "version switcher" and put it there. - ___ For branches out of maintenance: adapt the symlink in - /docs.python.org/release/X.Y to point to the recent version. - ___ Let the DE check if the docs are built and work all right. ___ If this is a major release: Tell the DE to adapt redirects for @@ -479,8 +462,29 @@ existing recent directory and twiddle the files in there for the new version number. - ___ Add a news section item to the front page by editing newsindex.yml. The - format should be pretty self evident. + ___ Update the version specific pages. + + ___ cd to `download/releases/X.Y.Z` + ___ Edit the version numbers in content.ht + ___ Update the md5 checksums + + ___ Comment out the "This is a preview release" or the "This is a + production release" paragraph as appropriate + + ___ Update the license in `download/releases/X.Y.Z/license` + + Note, you don't have to copy any release files into this directory; + they only live on dinsdale in the ftp directory. + + ___ Edit `download/releases/content.ht` to update the version numbers for + this release. There are a bunch of places you need to touch: + + ___ The subdirectory name as the first element in the Nav rows. + ___ Possibly the Releases section, and possibly in the experimental + releases section if this is an alpha, beta or release candidate. + + ___ Update the download page, editing `download/content.ht`. Pre-releases are + added only to the "Testing versions" list. ___ If this is a final release... @@ -496,28 +500,8 @@ ___ Add the new version to `doc/versions/content.ht`. - ___ Update the download page, editing `download/content.ht`. Pre-releases are - added only to the "Testing versions" list. - - ___ Edit `download/releases/content.ht` to update the version numbers for - this release. There are a bunch of places you need to touch: - - ___ The subdirectory name as the first element in the Nav rows. - ___ Possibly the Releases section, and possibly in the experimental - releases section if this is an alpha, beta or release candidate. - - ___ Update the version specific pages. - - ___ cd to `download/releases/X.Y.Z` - ___ Edit the version numbers in content.ht - ___ Comment out the link to the CHM file if this is not a final, - remove the comment if it is. - ___ Update the md5 checksums - - ___ Update the license in `download/releases/X.Y.Z/license` - - Note, you don't have to copy any release files into this directory; - they only live on dinsdale in the ftp directory. + ___ Add a news section item to the front page by editing newsindex.yml. The + format should be pretty self evident. ___ When everything looks good, `svn commit` in the data directory. This will trigger the live site to update itself, and at that point the -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Feb 9 12:56:22 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 9 Feb 2014 12:56:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNDM3?= =?utf-8?q?=3A_Fixed_43_potential_bugs_when_deleting_objects_references=2E?= Message-ID: <3fMTHB4m7kz7Ljg@mail.python.org> http://hg.python.org/cpython/rev/6b10943a5916 changeset: 89084:6b10943a5916 branch: 2.7 parent: 89067:d579866d6419 user: Serhiy Storchaka date: Sun Feb 09 13:14:04 2014 +0200 summary: Issue #20437: Fixed 43 potential bugs when deleting objects references. files: Mac/Modules/carbonevt/_CarbonEvtmodule.c | 3 +- Mac/Modules/list/_Listmodule.c | 3 +- Misc/NEWS | 2 + Modules/_bsddb.c | 21 ++++-------- Modules/_ctypes/_ctypes.c | 18 +++------ Modules/_elementtree.c | 8 ++-- Modules/_sqlite/connection.c | 3 +- Modules/_sqlite/cursor.c | 9 +--- Modules/cPickle.c | 3 +- Modules/cdmodule.c | 18 +++------ Modules/flmodule.c | 12 ++---- Modules/readline.c | 3 +- Modules/selectmodule.c | 3 +- Modules/svmodule.c | 3 +- Objects/tupleobject.c | 6 +-- Objects/unicodeobject.c | 6 +-- Python/ceval.c | 3 +- Python/sysmodule.c | 3 +- 18 files changed, 45 insertions(+), 82 deletions(-) diff --git a/Mac/Modules/carbonevt/_CarbonEvtmodule.c b/Mac/Modules/carbonevt/_CarbonEvtmodule.c --- a/Mac/Modules/carbonevt/_CarbonEvtmodule.c +++ b/Mac/Modules/carbonevt/_CarbonEvtmodule.c @@ -1051,8 +1051,7 @@ _err = RemoveEventHandler(_self->ob_itself); if (_err != noErr) return PyMac_Error(_err); _self->ob_itself = NULL; - Py_DECREF(_self->ob_callback); - _self->ob_callback = NULL; + Py_CLEAR(_self->ob_callback); Py_INCREF(Py_None); _res = Py_None; return _res; diff --git a/Mac/Modules/list/_Listmodule.c b/Mac/Modules/list/_Listmodule.c --- a/Mac/Modules/list/_Listmodule.c +++ b/Mac/Modules/list/_Listmodule.c @@ -76,8 +76,7 @@ static void ListObj_dealloc(ListObject *self) { - Py_XDECREF(self->ob_ldef_func); - self->ob_ldef_func = NULL; + Py_CLEAR(self->ob_ldef_func); SetListRefCon(self->ob_itself, (long)0); if (self->ob_must_be_disposed && self->ob_itself) LDispose(self->ob_itself); self->ob_type->tp_free((PyObject *)self); diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,8 @@ Core and Builtins ----------------- +- Issue #20437: Fixed 43 potential bugs when deleting objects references. + - Issue #20494: Ensure that free()d memory arenas are really released on POSIX systems supporting anonymous memory mappings. Patch by Charles-Fran?ois Natali. diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c --- a/Modules/_bsddb.c +++ b/Modules/_bsddb.c @@ -949,8 +949,7 @@ * DBTxns and closing any open DBs first. */ if (makeDBError(err)) { if (self->myenvobj) { - Py_DECREF(self->myenvobj); - self->myenvobj = NULL; + Py_CLEAR(self->myenvobj); } Py_DECREF(self); self = NULL; @@ -982,20 +981,16 @@ PyObject_ClearWeakRefs((PyObject *) self); } if (self->myenvobj) { - Py_DECREF(self->myenvobj); - self->myenvobj = NULL; + Py_CLEAR(self->myenvobj); } if (self->associateCallback != NULL) { - Py_DECREF(self->associateCallback); - self->associateCallback = NULL; + Py_CLEAR(self->associateCallback); } if (self->btCompareCallback != NULL) { - Py_DECREF(self->btCompareCallback); - self->btCompareCallback = NULL; + Py_CLEAR(self->btCompareCallback); } if (self->dupCompareCallback != NULL) { - Py_DECREF(self->dupCompareCallback); - self->dupCompareCallback = NULL; + Py_CLEAR(self->dupCompareCallback); } Py_DECREF(self->private_obj); PyObject_Del(self); @@ -1160,8 +1155,7 @@ PyErr_Clear(); } - Py_XDECREF(self->event_notifyCallback); - self->event_notifyCallback = NULL; + Py_CLEAR(self->event_notifyCallback); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) self); @@ -1640,8 +1634,7 @@ MYDB_END_ALLOW_THREADS; if (err) { - Py_XDECREF(secondaryDB->associateCallback); - secondaryDB->associateCallback = NULL; + Py_CLEAR(secondaryDB->associateCallback); secondaryDB->primaryDBType = 0; } diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -194,10 +194,8 @@ if (-1 == PyDict_DelItem(self->dict, self->key)) /* XXX Error context */ PyErr_WriteUnraisable(Py_None); - Py_DECREF(self->key); - self->key = NULL; - Py_DECREF(self->dict); - self->dict = NULL; + Py_CLEAR(self->key); + Py_CLEAR(self->dict); } Py_INCREF(Py_None); return Py_None; @@ -3040,10 +3038,8 @@ PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob) { if (ob == NULL) { - Py_XDECREF(self->restype); - self->restype = NULL; - Py_XDECREF(self->checker); - self->checker = NULL; + Py_CLEAR(self->restype); + Py_CLEAR(self->checker); return 0; } if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) { @@ -3086,10 +3082,8 @@ PyObject *converters; if (ob == NULL || ob == Py_None) { - Py_XDECREF(self->converters); - self->converters = NULL; - Py_XDECREF(self->argtypes); - self->argtypes = NULL; + Py_CLEAR(self->converters); + Py_CLEAR(self->argtypes); } else { converters = converters_from_argtypes(ob); if (!converters) diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2739,10 +2739,10 @@ target->events = events; /* clear out existing events */ - Py_XDECREF(target->start_event_obj); target->start_event_obj = NULL; - Py_XDECREF(target->end_event_obj); target->end_event_obj = NULL; - Py_XDECREF(target->start_ns_event_obj); target->start_ns_event_obj = NULL; - Py_XDECREF(target->end_ns_event_obj); target->end_ns_event_obj = NULL; + Py_CLEAR(target->start_event_obj); + Py_CLEAR(target->end_event_obj); + Py_CLEAR(target->start_ns_event_obj); + Py_CLEAR(target->end_ns_event_obj); if (event_set == Py_None) { /* default is "end" only */ diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -369,8 +369,7 @@ if (self->apsw_connection) { ret = PyObject_CallMethod(self->apsw_connection, "close", ""); Py_XDECREF(ret); - Py_XDECREF(self->apsw_connection); - self->apsw_connection = NULL; + Py_CLEAR(self->apsw_connection); self->db = NULL; } else { Py_BEGIN_ALLOW_THREADS diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -231,8 +231,7 @@ if (converter != Py_None) { Py_DECREF(converter); } - Py_XDECREF(self->row_cast_map); - self->row_cast_map = NULL; + Py_CLEAR(self->row_cast_map); return -1; } @@ -468,8 +467,7 @@ allow_8bit_chars = ((self->connection->text_factory != (PyObject*)&PyUnicode_Type) && (self->connection->text_factory != pysqlite_OptimizedUnicode)); - Py_XDECREF(self->next_row); - self->next_row = NULL; + Py_CLEAR(self->next_row); if (multiple) { /* executemany() */ @@ -896,8 +894,7 @@ if (!self->next_row) { if (self->statement) { (void)pysqlite_statement_reset(self->statement); - Py_DECREF(self->statement); - self->statement = NULL; + Py_CLEAR(self->statement); } return NULL; } diff --git a/Modules/cPickle.c b/Modules/cPickle.c --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -324,8 +324,7 @@ #define FREE_ARG_TUP(self) { \ if (Py_REFCNT(self->arg) > 1) { \ - Py_DECREF(self->arg); \ - self->arg=NULL; \ + Py_CLEAR(self->arg); \ } \ } diff --git a/Modules/cdmodule.c b/Modules/cdmodule.c --- a/Modules/cdmodule.c +++ b/Modules/cdmodule.c @@ -535,10 +535,8 @@ /* no sense in keeping the callbacks, so remove them */ for (i = 0; i < NCALLBACKS; i++) { - Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallback); - self->ob_cdcallbacks[i].ob_cdcallback = NULL; - Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg); - self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL; + Py_CLEAR(self->ob_cdcallbacks[i].ob_cdcallback); + Py_CLEAR(self->ob_cdcallbacks[i].ob_cdcallbackarg); } Py_INCREF(Py_None); @@ -588,11 +586,9 @@ CDremovecallback(self->ob_cdparser, (CDDATATYPES) type); - Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallback); - self->ob_cdcallbacks[type].ob_cdcallback = NULL; + Py_CLEAR(self->ob_cdcallbacks[type].ob_cdcallback); - Py_XDECREF(self->ob_cdcallbacks[type].ob_cdcallbackarg); - self->ob_cdcallbacks[type].ob_cdcallbackarg = NULL; + Py_CLEAR(self->ob_cdcallbacks[type].ob_cdcallbackarg); Py_INCREF(Py_None); return Py_None; @@ -668,10 +664,8 @@ int i; for (i = 0; i < NCALLBACKS; i++) { - Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallback); - self->ob_cdcallbacks[i].ob_cdcallback = NULL; - Py_XDECREF(self->ob_cdcallbacks[i].ob_cdcallbackarg); - self->ob_cdcallbacks[i].ob_cdcallbackarg = NULL; + Py_CLEAR(self->ob_cdcallbacks[i].ob_cdcallback); + Py_CLEAR(self->ob_cdcallbacks[i].ob_cdcallbackarg); } CDdeleteparser(self->ob_cdparser); PyObject_Del(self); diff --git a/Modules/flmodule.c b/Modules/flmodule.c --- a/Modules/flmodule.c +++ b/Modules/flmodule.c @@ -97,10 +97,8 @@ { int i, n; - Py_XDECREF(g->ob_callback); - g->ob_callback = NULL; - Py_XDECREF(g->ob_callback_arg); - g->ob_callback_arg = NULL; + Py_CLEAR(g->ob_callback); + Py_CLEAR(g->ob_callback_arg); if (allgenerics == NULL) return; /* No objects known yet */ n = PyList_Size(allgenerics); @@ -132,10 +130,8 @@ /* The object is now unreachable for do_forms and check_forms, so delete it from the list of known objects */ - Py_XDECREF(g->ob_callback); - g->ob_callback = NULL; - Py_XDECREF(g->ob_callback_arg); - g->ob_callback_arg = NULL; + Py_CLEAR(g->ob_callback); + Py_CLEAR(g->ob_callback_arg); PyList_SetItem(allgenerics, i, (PyObject *)NULL); nfreeslots++; } diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -206,8 +206,7 @@ if (!PyArg_ParseTuple(args, buf, &function)) return NULL; if (function == Py_None) { - Py_XDECREF(*hook_var); - *hook_var = NULL; + Py_CLEAR(*hook_var); } else if (PyCallable_Check(function)) { PyObject *tmp = *hook_var; diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -71,8 +71,7 @@ { int i; for (i = 0; i < FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) { - Py_XDECREF(fd2obj[i].obj); - fd2obj[i].obj = NULL; + Py_CLEAR(fd2obj[i].obj); } fd2obj[0].sentinel = -1; } diff --git a/Modules/svmodule.c b/Modules/svmodule.c --- a/Modules/svmodule.c +++ b/Modules/svmodule.c @@ -279,8 +279,7 @@ (void)svUnlockCaptureData(self->ob_svideo->ob_svideo, self->ob_capture); self->ob_capture = NULL; - Py_DECREF(self->ob_svideo); - self->ob_svideo = NULL; + Py_CLEAR(self->ob_svideo); } PyObject_Del(self); } diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -881,8 +881,7 @@ _Py_ForgetReference((PyObject *) v); /* DECREF items deleted by shrinkage */ for (i = newsize; i < oldsize; i++) { - Py_XDECREF(v->ob_item[i]); - v->ob_item[i] = NULL; + Py_CLEAR(v->ob_item[i]); } sv = PyObject_GC_Resize(PyTupleObject, v, newsize); if (sv == NULL) { @@ -928,8 +927,7 @@ #if PyTuple_MAXSAVESIZE > 0 /* empty tuples are used all over the place and applications may * rely on the fact that an empty tuple is a singleton. */ - Py_XDECREF(free_list[0]); - free_list[0] = NULL; + Py_CLEAR(free_list[0]); (void)PyTuple_ClearFreeList(); #endif diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3520,8 +3520,7 @@ goto onError; return; onError: - Py_DECREF(*exceptionObject); - *exceptionObject = NULL; + Py_CLEAR(*exceptionObject); } } @@ -4826,8 +4825,7 @@ goto onError; return; onError: - Py_DECREF(*exceptionObject); - *exceptionObject = NULL; + Py_CLEAR(*exceptionObject); } } diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3240,8 +3240,7 @@ if (co->co_flags & CO_GENERATOR) { /* Don't need to keep the reference to f_back, it will be set * when the generator is resumed. */ - Py_XDECREF(f->f_back); - f->f_back = NULL; + Py_CLEAR(f->f_back); PCALL(PCALL_GENERATOR); diff --git a/Python/sysmodule.c b/Python/sysmodule.c --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -367,8 +367,7 @@ result = call_trampoline(tstate, callback, frame, what, arg); if (result == NULL) { PyEval_SetTrace(NULL, NULL); - Py_XDECREF(frame->f_trace); - frame->f_trace = NULL; + Py_CLEAR(frame->f_trace); return -1; } if (result != Py_None) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 12:56:24 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 9 Feb 2014 12:56:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNDM3?= =?utf-8?q?=3A_Fixed_21_potential_bugs_when_deleting_objects_references=2E?= Message-ID: <3fMTHD15gfz7LmF@mail.python.org> http://hg.python.org/cpython/rev/6adac0d9b933 changeset: 89085:6adac0d9b933 branch: 3.3 parent: 89068:c2538789c8cf user: Serhiy Storchaka date: Sun Feb 09 13:33:53 2014 +0200 summary: Issue #20437: Fixed 21 potential bugs when deleting objects references. files: Misc/NEWS | 2 ++ Modules/_ctypes/_ctypes.c | 18 ++++++------------ Modules/_sqlite/cursor.c | 9 +++------ Modules/posixmodule.c | 3 +-- Modules/pyexpat.c | 3 +-- Modules/readline.c | 5 ++--- Modules/selectmodule.c | 3 +-- Modules/signalmodule.c | 9 +++------ Modules/syslogmodule.c | 3 +-- Modules/zlibmodule.c | 3 +-- Objects/frameobject.c | 3 +-- Objects/tupleobject.c | 6 ++---- Objects/unicodeobject.c | 12 ++++-------- Python/ceval.c | 9 +++------ Python/import.c | 6 ++---- Python/sysmodule.c | 3 +-- 16 files changed, 34 insertions(+), 63 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #20437: Fixed 21 potential bugs when deleting objects references. + - Issue #20538: UTF-7 incremental decoder produced inconsistant string when input was truncated in BASE64 section. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -159,10 +159,8 @@ if (-1 == PyDict_DelItem(self->dict, self->key)) /* XXX Error context */ PyErr_WriteUnraisable(Py_None); - Py_DECREF(self->key); - self->key = NULL; - Py_DECREF(self->dict); - self->dict = NULL; + Py_CLEAR(self->key); + Py_CLEAR(self->dict); } Py_INCREF(Py_None); return Py_None; @@ -2930,10 +2928,8 @@ PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob) { if (ob == NULL) { - Py_XDECREF(self->restype); - self->restype = NULL; - Py_XDECREF(self->checker); - self->checker = NULL; + Py_CLEAR(self->restype); + Py_CLEAR(self->checker); return 0; } if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) { @@ -2976,10 +2972,8 @@ PyObject *converters; if (ob == NULL || ob == Py_None) { - Py_XDECREF(self->converters); - self->converters = NULL; - Py_XDECREF(self->argtypes); - self->argtypes = NULL; + Py_CLEAR(self->converters); + Py_CLEAR(self->argtypes); } else { converters = converters_from_argtypes(ob); if (!converters) diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -230,8 +230,7 @@ if (converter != Py_None) { Py_DECREF(converter); } - Py_XDECREF(self->row_cast_map); - self->row_cast_map = NULL; + Py_CLEAR(self->row_cast_map); return -1; } @@ -443,8 +442,7 @@ self->locked = 1; self->reset = 0; - Py_XDECREF(self->next_row); - self->next_row = NULL; + Py_CLEAR(self->next_row); if (multiple) { /* executemany() */ @@ -860,8 +858,7 @@ if (!self->next_row) { if (self->statement) { (void)pysqlite_statement_reset(self->statement); - Py_DECREF(self->statement); - self->statement = NULL; + Py_CLEAR(self->statement); } return NULL; } diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -693,8 +693,7 @@ static void path_cleanup(path_t *path) { if (path->cleanup) { - Py_DECREF(path->cleanup); - path->cleanup = NULL; + Py_CLEAR(path->cleanup); } } diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -314,8 +314,7 @@ } else { if (trace_frame(tstate, f, PyTrace_RETURN, res) < 0) { - Py_XDECREF(res); - res = NULL; + Py_CLEAR(res); } } #else diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -231,8 +231,7 @@ if (!PyArg_ParseTuple(args, buf, &function)) return NULL; if (function == Py_None) { - Py_XDECREF(*hook_var); - *hook_var = NULL; + Py_CLEAR(*hook_var); } else if (PyCallable_Check(function)) { PyObject *tmp = *hook_var; @@ -827,7 +826,7 @@ (r != Py_None && PyLong_AsLong(r) == -1 && PyErr_Occurred())) { goto error; } - Py_XDECREF(r); r=NULL; + Py_CLEAR(r); if (0) { error: diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -74,8 +74,7 @@ { int i; for (i = 0; i < FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) { - Py_XDECREF(fd2obj[i].obj); - fd2obj[i].obj = NULL; + Py_CLEAR(fd2obj[i].obj); } fd2obj[0].sentinel = -1; } diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1305,12 +1305,9 @@ Py_XDECREF(func); } - Py_XDECREF(IntHandler); - IntHandler = NULL; - Py_XDECREF(DefaultHandler); - DefaultHandler = NULL; - Py_XDECREF(IgnoreHandler); - IgnoreHandler = NULL; + Py_CLEAR(IntHandler); + Py_CLEAR(DefaultHandler); + Py_CLEAR(IgnoreHandler); } diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c --- a/Modules/syslogmodule.c +++ b/Modules/syslogmodule.c @@ -197,8 +197,7 @@ { if (S_log_open) { closelog(); - Py_XDECREF(S_ident_o); - S_ident_o = NULL; + Py_CLEAR(S_ident_o); S_log_open = 0; } Py_INCREF(Py_None); diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -392,8 +392,7 @@ } error: - Py_XDECREF(self); - self = NULL; + Py_CLEAR(self); success: if (zdict.buf != NULL) PyBuffer_Release(&zdict); diff --git a/Objects/frameobject.c b/Objects/frameobject.c --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -952,8 +952,7 @@ PyFrame_Fini(void) { (void)PyFrame_ClearFreeList(); - Py_XDECREF(builtin_object); - builtin_object = NULL; + Py_CLEAR(builtin_object); } /* Print summary info about the state of the optimized allocator */ diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -866,8 +866,7 @@ _Py_ForgetReference((PyObject *) v); /* DECREF items deleted by shrinkage */ for (i = newsize; i < oldsize; i++) { - Py_XDECREF(v->ob_item[i]); - v->ob_item[i] = NULL; + Py_CLEAR(v->ob_item[i]); } sv = PyObject_GC_Resize(PyTupleObject, v, newsize); if (sv == NULL) { @@ -913,8 +912,7 @@ #if PyTuple_MAXSAVESIZE > 0 /* empty tuples are used all over the place and applications may * rely on the fact that an empty tuple is a singleton. */ - Py_XDECREF(free_list[0]); - free_list[0] = NULL; + Py_CLEAR(free_list[0]); (void)PyTuple_ClearFreeList(); #endif diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1846,8 +1846,7 @@ { _Py_Identifier *tmp, *s = static_strings; while (s) { - Py_DECREF(s->object); - s->object = NULL; + Py_CLEAR(s->object); tmp = s->next; s->next = NULL; s = tmp; @@ -4082,8 +4081,7 @@ return; onError: - Py_DECREF(*exceptionObject); - *exceptionObject = NULL; + Py_CLEAR(*exceptionObject); } /* error handling callback helper: @@ -6224,8 +6222,7 @@ goto onError; return; onError: - Py_DECREF(*exceptionObject); - *exceptionObject = NULL; + Py_CLEAR(*exceptionObject); } } @@ -8225,8 +8222,7 @@ goto onError; return; onError: - Py_DECREF(*exceptionObject); - *exceptionObject = NULL; + Py_CLEAR(*exceptionObject); } } diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3049,8 +3049,7 @@ if (call_trace(tstate->c_tracefunc, tstate->c_traceobj, f, PyTrace_RETURN, retval)) { - Py_XDECREF(retval); - retval = NULL; + Py_CLEAR(retval); why = WHY_EXCEPTION; } } @@ -3068,8 +3067,7 @@ else if (call_trace(tstate->c_profilefunc, tstate->c_profileobj, f, PyTrace_RETURN, retval)) { - Py_XDECREF(retval); - retval = NULL; + Py_CLEAR(retval); /* why = WHY_EXCEPTION; */ } } @@ -3426,8 +3424,7 @@ if (co->co_flags & CO_GENERATOR) { /* Don't need to keep the reference to f_back, it will be set * when the generator is resumed. */ - Py_XDECREF(f->f_back); - f->f_back = NULL; + Py_CLEAR(f->f_back); PCALL(PCALL_GENERATOR); diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -253,8 +253,7 @@ void _PyImport_Fini(void) { - Py_XDECREF(extensions); - extensions = NULL; + Py_CLEAR(extensions); #ifdef WITH_THREAD if (import_lock != NULL) { PyThread_free_lock(import_lock); @@ -497,8 +496,7 @@ /* Somebody already imported the module, likely under a different name. XXX this should really not happen. */ - Py_DECREF(def->m_base.m_copy); - def->m_base.m_copy = NULL; + Py_CLEAR(def->m_base.m_copy); } dict = PyModule_GetDict(mod); if (dict == NULL) diff --git a/Python/sysmodule.c b/Python/sysmodule.c --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -395,8 +395,7 @@ result = call_trampoline(tstate, callback, frame, what, arg); if (result == NULL) { PyEval_SetTrace(NULL, NULL); - Py_XDECREF(frame->f_trace); - frame->f_trace = NULL; + Py_CLEAR(frame->f_trace); return -1; } if (result != Py_None) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 12:56:25 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 9 Feb 2014 12:56:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320437=3A_Fixed_22_potential_bugs_when_deleting_?= =?utf-8?q?objects_references=2E?= Message-ID: <3fMTHF4PZXz7Ljg@mail.python.org> http://hg.python.org/cpython/rev/3110fb3095a2 changeset: 89086:3110fb3095a2 parent: 89083:29d9638bf449 parent: 89085:6adac0d9b933 user: Serhiy Storchaka date: Sun Feb 09 13:46:20 2014 +0200 summary: Issue #20437: Fixed 22 potential bugs when deleting objects references. files: Misc/NEWS | 2 ++ Modules/_ctypes/_ctypes.c | 18 ++++++------------ Modules/_sqlite/cursor.c | 9 +++------ Modules/posixmodule.c | 3 +-- Modules/pyexpat.c | 3 +-- Modules/readline.c | 5 ++--- Modules/selectmodule.c | 3 +-- Modules/signalmodule.c | 9 +++------ Modules/syslogmodule.c | 3 +-- Modules/zlibmodule.c | 3 +-- Objects/tupleobject.c | 6 ++---- Objects/unicodeobject.c | 15 +++++---------- Python/ceval.c | 9 +++------ Python/import.c | 6 ++---- Python/sysmodule.c | 3 +-- 15 files changed, 34 insertions(+), 63 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #20437: Fixed 22 potential bugs when deleting objects references. + - Issue #20500: Displaying an exception at interpreter shutdown no longer risks triggering an assertion failure in PyObject_Str. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -159,10 +159,8 @@ if (-1 == PyDict_DelItem(self->dict, self->key)) /* XXX Error context */ PyErr_WriteUnraisable(Py_None); - Py_DECREF(self->key); - self->key = NULL; - Py_DECREF(self->dict); - self->dict = NULL; + Py_CLEAR(self->key); + Py_CLEAR(self->dict); } Py_INCREF(Py_None); return Py_None; @@ -2934,10 +2932,8 @@ PyCFuncPtr_set_restype(PyCFuncPtrObject *self, PyObject *ob) { if (ob == NULL) { - Py_XDECREF(self->restype); - self->restype = NULL; - Py_XDECREF(self->checker); - self->checker = NULL; + Py_CLEAR(self->restype); + Py_CLEAR(self->checker); return 0; } if (ob != Py_None && !PyType_stgdict(ob) && !PyCallable_Check(ob)) { @@ -2980,10 +2976,8 @@ PyObject *converters; if (ob == NULL || ob == Py_None) { - Py_XDECREF(self->converters); - self->converters = NULL; - Py_XDECREF(self->argtypes); - self->argtypes = NULL; + Py_CLEAR(self->converters); + Py_CLEAR(self->argtypes); } else { converters = converters_from_argtypes(ob); if (!converters) diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -229,8 +229,7 @@ if (converter != Py_None) { Py_DECREF(converter); } - Py_XDECREF(self->row_cast_map); - self->row_cast_map = NULL; + Py_CLEAR(self->row_cast_map); return -1; } @@ -447,8 +446,7 @@ self->locked = 1; self->reset = 0; - Py_XDECREF(self->next_row); - self->next_row = NULL; + Py_CLEAR(self->next_row); if (multiple) { /* executemany() */ @@ -864,8 +862,7 @@ if (!self->next_row) { if (self->statement) { (void)pysqlite_statement_reset(self->statement); - Py_DECREF(self->statement); - self->statement = NULL; + Py_CLEAR(self->statement); } return NULL; } diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -780,8 +780,7 @@ static void path_cleanup(path_t *path) { if (path->cleanup) { - Py_DECREF(path->cleanup); - path->cleanup = NULL; + Py_CLEAR(path->cleanup); } } diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -317,8 +317,7 @@ } else { if (trace_frame(tstate, f, PyTrace_RETURN, res) < 0) { - Py_XDECREF(res); - res = NULL; + Py_CLEAR(res); } } #else diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -281,8 +281,7 @@ if (!PyArg_ParseTuple(args, buf, &function)) return NULL; if (function == Py_None) { - Py_XDECREF(*hook_var); - *hook_var = NULL; + Py_CLEAR(*hook_var); } else if (PyCallable_Check(function)) { PyObject *tmp = *hook_var; @@ -885,7 +884,7 @@ (r != Py_None && PyLong_AsLong(r) == -1 && PyErr_Occurred())) { goto error; } - Py_XDECREF(r); r=NULL; + Py_CLEAR(r); if (0) { error: diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -66,8 +66,7 @@ { int i; for (i = 0; i < FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) { - Py_XDECREF(fd2obj[i].obj); - fd2obj[i].obj = NULL; + Py_CLEAR(fd2obj[i].obj); } fd2obj[0].sentinel = -1; } diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1305,12 +1305,9 @@ Py_XDECREF(func); } - Py_XDECREF(IntHandler); - IntHandler = NULL; - Py_XDECREF(DefaultHandler); - DefaultHandler = NULL; - Py_XDECREF(IgnoreHandler); - IgnoreHandler = NULL; + Py_CLEAR(IntHandler); + Py_CLEAR(DefaultHandler); + Py_CLEAR(IgnoreHandler); } diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c --- a/Modules/syslogmodule.c +++ b/Modules/syslogmodule.c @@ -197,8 +197,7 @@ { if (S_log_open) { closelog(); - Py_XDECREF(S_ident_o); - S_ident_o = NULL; + Py_CLEAR(S_ident_o); S_log_open = 0; } Py_INCREF(Py_None); diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -463,8 +463,7 @@ } error: - Py_XDECREF(self); - self = NULL; + Py_CLEAR(self); success: return (PyObject*)self; } diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -879,8 +879,7 @@ _Py_ForgetReference((PyObject *) v); /* DECREF items deleted by shrinkage */ for (i = newsize; i < oldsize; i++) { - Py_XDECREF(v->ob_item[i]); - v->ob_item[i] = NULL; + Py_CLEAR(v->ob_item[i]); } sv = PyObject_GC_Resize(PyTupleObject, v, newsize); if (sv == NULL) { @@ -926,8 +925,7 @@ #if PyTuple_MAXSAVESIZE > 0 /* empty tuples are used all over the place and applications may * rely on the fact that an empty tuple is a singleton. */ - Py_XDECREF(free_list[0]); - free_list[0] = NULL; + Py_CLEAR(free_list[0]); (void)PyTuple_ClearFreeList(); #endif diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1902,8 +1902,7 @@ { _Py_Identifier *tmp, *s = static_strings; while (s) { - Py_DECREF(s->object); - s->object = NULL; + Py_CLEAR(s->object); tmp = s->next; s->next = NULL; s = tmp; @@ -4005,8 +4004,7 @@ return; onError: - Py_DECREF(*exceptionObject); - *exceptionObject = NULL; + Py_CLEAR(*exceptionObject); } #ifdef HAVE_MBCS @@ -6366,8 +6364,7 @@ goto onError; return; onError: - Py_DECREF(*exceptionObject); - *exceptionObject = NULL; + Py_CLEAR(*exceptionObject); } } @@ -8410,8 +8407,7 @@ goto onError; return; onError: - Py_DECREF(*exceptionObject); - *exceptionObject = NULL; + Py_CLEAR(*exceptionObject); } } @@ -13502,8 +13498,7 @@ PyObject *newbuffer; newbuffer = resize_compact(writer->buffer, writer->pos); if (newbuffer == NULL) { - Py_DECREF(writer->buffer); - writer->buffer = NULL; + Py_CLEAR(writer->buffer); return NULL; } writer->buffer = newbuffer; diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3189,8 +3189,7 @@ if (call_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, f, PyTrace_RETURN, retval)) { - Py_XDECREF(retval); - retval = NULL; + Py_CLEAR(retval); why = WHY_EXCEPTION; } } @@ -3209,8 +3208,7 @@ else if (call_trace(tstate->c_profilefunc, tstate->c_profileobj, tstate, f, PyTrace_RETURN, retval)) { - Py_XDECREF(retval); - retval = NULL; + Py_CLEAR(retval); /* why = WHY_EXCEPTION; */ } } @@ -3568,8 +3566,7 @@ if (co->co_flags & CO_GENERATOR) { /* Don't need to keep the reference to f_back, it will be set * when the generator is resumed. */ - Py_XDECREF(f->f_back); - f->f_back = NULL; + Py_CLEAR(f->f_back); PCALL(PCALL_GENERATOR); diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -349,8 +349,7 @@ void _PyImport_Fini(void) { - Py_XDECREF(extensions); - extensions = NULL; + Py_CLEAR(extensions); #ifdef WITH_THREAD if (import_lock != NULL) { PyThread_free_lock(import_lock); @@ -598,8 +597,7 @@ /* Somebody already imported the module, likely under a different name. XXX this should really not happen. */ - Py_DECREF(def->m_base.m_copy); - def->m_base.m_copy = NULL; + Py_CLEAR(def->m_base.m_copy); } dict = PyModule_GetDict(mod); if (dict == NULL) diff --git a/Python/sysmodule.c b/Python/sysmodule.c --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -430,8 +430,7 @@ result = call_trampoline(callback, frame, what, arg); if (result == NULL) { PyEval_SetTrace(NULL, NULL); - Py_XDECREF(frame->f_trace); - frame->f_trace = NULL; + Py_CLEAR(frame->f_trace); return -1; } if (result != Py_None) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 13:14:10 2014 From: python-checkins at python.org (victor.stinner) Date: Sun, 9 Feb 2014 13:14:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320571=3A_skip_tes?= =?utf-8?q?t=5Freadline=28=29_of_test=5Fcodecs_for_Windows_code_page_65001?= =?utf-8?q?=2E?= Message-ID: <3fMTgk4vBzz7LmF@mail.python.org> http://hg.python.org/cpython/rev/4f6499fc2f09 changeset: 89087:4f6499fc2f09 user: Victor Stinner date: Sun Feb 09 13:11:53 2014 +0100 summary: Issue #20571: skip test_readline() of test_codecs for Windows code page 65001. The decoder does not support partial decoding yet for this code page. files: Lib/test/test_codecs.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -890,6 +890,9 @@ "\U00010fff\uD800") self.assertTrue(codecs.lookup_error("surrogatepass")) + def test_readline(self): + self.skipTest("issue #20571: code page 65001 codec does not " + "support partial decoder yet") class UTF7Test(ReadTest, unittest.TestCase): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 14:54:15 2014 From: python-checkins at python.org (eli.bendersky) Date: Sun, 9 Feb 2014 14:54:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_typo_in_library/ipc=2E?= =?utf-8?q?rst?= Message-ID: <3fMWvC07BWz7LjM@mail.python.org> http://hg.python.org/cpython/rev/9344d5dbcbbb changeset: 89088:9344d5dbcbbb user: Eli Bendersky date: Sun Feb 09 05:54:13 2014 -0800 summary: Fix typo in library/ipc.rst files: Doc/library/ipc.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/ipc.rst b/Doc/library/ipc.rst --- a/Doc/library/ipc.rst +++ b/Doc/library/ipc.rst @@ -9,7 +9,7 @@ Some modules only work for two processes that are on the same machine, e.g. :mod:`signal` and :mod:`mmap`. Other modules support networking protocols -that two or more processes can used to communicate across machines. +that two or more processes can use to communicate across machines. The list of modules described in this chapter is: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 15:07:48 2014 From: python-checkins at python.org (eli.bendersky) Date: Sun, 9 Feb 2014 15:07:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Various_formatting_=26_gra?= =?utf-8?q?mmar_fixes_in_asyncio*_docs=2E?= Message-ID: <3fMXBr6Nxnz7LjN@mail.python.org> http://hg.python.org/cpython/rev/76713f4d9f0f changeset: 89089:76713f4d9f0f user: Eli Bendersky date: Sun Feb 09 06:07:47 2014 -0800 summary: Various formatting & grammar fixes in asyncio* docs. files: Doc/library/asyncio-dev.rst | 2 +- Doc/library/asyncio-eventloop.rst | 8 ++++---- Doc/library/asyncio.rst | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -44,7 +44,7 @@ .. _asyncio-handle-blocking: -Handle correctly blocking functions +Handle blocking functions correctly ----------------------------------- Blocking functions should not be called directly. For example, if a function diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -8,15 +8,15 @@ The event loop is the central execution device provided by :mod:`asyncio`. It provides multiple facilities, amongst which: -* Registering, executing and cancelling delayed calls (timeouts) +* Registering, executing and cancelling delayed calls (timeouts). * Creating client and server :ref:`transports ` for various - kinds of communication + kinds of communication. * Launching subprocesses and the associated :ref:`transports ` - for communication with an external program + for communication with an external program. -* Delegating costly function calls to a pool of threads +* Delegating costly function calls to a pool of threads. Event loop functions -------------------- diff --git a/Doc/library/asyncio.rst b/Doc/library/asyncio.rst --- a/Doc/library/asyncio.rst +++ b/Doc/library/asyncio.rst @@ -30,7 +30,7 @@ * coroutines and tasks based on ``yield from`` (:PEP:`380`), to help write concurrent code in a sequential fashion; -* cancellation support for Futures and coroutines; +* cancellation support for :class:`Future`\s and coroutines; * :ref:`synchronization primitives ` for use between coroutines in a single thread, mimicking those in the :mod:`threading` module; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 9 15:55:58 2014 From: python-checkins at python.org (eli.bendersky) Date: Sun, 9 Feb 2014 15:55:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_More_complete_documentatio?= =?utf-8?q?n_of_event_loops_and_policies=2E?= Message-ID: <3fMYGQ6lYbz7LjM@mail.python.org> http://hg.python.org/cpython/rev/3e62c6c3977e changeset: 89090:3e62c6c3977e user: Eli Bendersky date: Sun Feb 09 06:55:58 2014 -0800 summary: More complete documentation of event loops and policies. Documented the AbstractEventLoopPolicy interface explicitly and explained the relation between the global loop & policy access functions. Added an initial section that explains the connections in general terms. Documented missing XXX methods. files: Doc/library/asyncio-eventloop.rst | 69 ++++++++++++++---- 1 files changed, 54 insertions(+), 15 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -13,44 +13,83 @@ * Creating client and server :ref:`transports ` for various kinds of communication. -* Launching subprocesses and the associated :ref:`transports ` - for communication with an external program. +* Launching subprocesses and the associated :ref:`transports + ` for communication with an external program. * Delegating costly function calls to a pool of threads. +Event loop policies and the default policy +------------------------------------------ + +Event loop management is abstracted with a *policy* pattern, to provide maximal +flexibility for custom platforms and frameworks. Throughout the execution of a +process, a single global policy object manages the event loops available to the +process based on the calling context. A policy is an object implementing the +:class:`AbstractEventLoopPolicy` interface. + +For most users of :mod:`asyncio`, policies never have to be dealt with +explicitly, since the default global policy is sufficient. + +The default policy defines context as the current thread, and manages an event +loop per thread that interacts with :mod:`asyncio`. The module-level functions +:func:`get_event_loop` and :func:`set_event_loop` provide convenient access to +event loops managed by the default policy. + Event loop functions -------------------- -The easiest way to get an event loop is to call the :func:`get_event_loop` -function. +The following functions are convenient shortcuts to accessing the methods of the +global policy. Note that this provides access to the default policy, unless an +alternative policy was set by calling :func:`set_event_loop_policy` earlier in +the execution of the process. .. function:: get_event_loop() - Get the event loop for current context. Returns an event loop object - implementing :class:`BaseEventLoop` interface, or raises an exception in case no - event loop has been set for the current context and the current policy does - not specify to create one. It should never return ``None``. + Equivalent to calling ``get_event_loop_policy().get_event_loop()``. .. function:: set_event_loop(loop) - XXX + Equivalent to calling ``get_event_loop_policy().set_event_loop(loop)``. .. function:: new_event_loop() - XXX + Equivalent to calling ``get_event_loop_policy().new_event_loop()``. +Event loop policy interface +--------------------------- -Event loop policy ------------------ +An event loop policy must implement the following interface: + +.. class:: AbstractEventLoopPolicy + + .. method:: get_event_loop() + + Get the event loop for current context. Returns an event loop object + implementing :class:`BaseEventLoop` interface, or raises an exception in case + no event loop has been set for the current context and the current policy + does not specify to create one. It should never return ``None``. + + .. method:: set_event_loop(loop) + + Set the event loop of the current context to *loop*. + + .. method:: new_event_loop() + + Create and return a new event loop object according to this policy's rules. + If there's need to set this loop as the event loop of the current context, + :meth`set_event_loop` must be called explicitly. + +Access to the global loop policy +-------------------------------- .. function:: get_event_loop_policy() - XXX + Get the current event loop policy. .. function:: set_event_loop_policy(policy) - XXX - + Set the current event loop policy. If *policy* is ``None``, the default + policy is restored. Run an event loop ----------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 00:47:19 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 10 Feb 2014 00:47:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Tulip_issue_112?= =?utf-8?q?=3A_Inline_make=5Fhandle=28=29_into_Handle_constructor?= Message-ID: <3fMn3W5gjVz7LjN@mail.python.org> http://hg.python.org/cpython/rev/aa7ce6f74303 changeset: 89091:aa7ce6f74303 user: Victor Stinner date: Mon Feb 10 00:45:44 2014 +0100 summary: asyncio: Tulip issue 112: Inline make_handle() into Handle constructor files: Lib/asyncio/base_events.py | 2 +- Lib/asyncio/events.py | 7 +------ Lib/asyncio/selector_events.py | 4 ++-- Lib/asyncio/test_utils.py | 4 ++-- Lib/asyncio/unix_events.py | 2 +- Lib/test/test_asyncio/test_events.py | 4 ++-- 6 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -240,7 +240,7 @@ Any positional arguments after the callback will be passed to the callback when it is called. """ - handle = events.make_handle(callback, args) + handle = events.Handle(callback, args) self._ready.append(handle) return handle diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -20,6 +20,7 @@ """Object returned by callback registration methods.""" def __init__(self, callback, args): + assert not isinstance(callback, Handle), 'A Handle is not a callback' self._callback = callback self._args = args self._cancelled = False @@ -42,12 +43,6 @@ self = None # Needed to break cycles when an exception occurs. -def make_handle(callback, args): - # TODO: Inline this? Or make it a private EventLoop method? - assert not isinstance(callback, Handle), 'A Handle is not a callback' - return Handle(callback, args) - - class TimerHandle(Handle): """Object returned by timed callback registration methods.""" diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -132,7 +132,7 @@ def add_reader(self, fd, callback, *args): """Add a reader callback.""" - handle = events.make_handle(callback, args) + handle = events.Handle(callback, args) try: key = self._selector.get_key(fd) except KeyError: @@ -167,7 +167,7 @@ def add_writer(self, fd, callback, *args): """Add a writer callback..""" - handle = events.make_handle(callback, args) + handle = events.Handle(callback, args) try: key = self._selector.get_key(fd) except KeyError: diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -216,7 +216,7 @@ raise AssertionError("Time generator is not finished") def add_reader(self, fd, callback, *args): - self.readers[fd] = events.make_handle(callback, args) + self.readers[fd] = events.Handle(callback, args) def remove_reader(self, fd): self.remove_reader_count[fd] += 1 @@ -235,7 +235,7 @@ handle._args, args) def add_writer(self, fd, callback, *args): - self.writers[fd] = events.make_handle(callback, args) + self.writers[fd] = events.Handle(callback, args) def remove_writer(self, fd): self.remove_writer_count[fd] += 1 diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -64,7 +64,7 @@ except ValueError as exc: raise RuntimeError(str(exc)) - handle = events.make_handle(callback, args) + handle = events.Handle(callback, args) self._signal_handlers[sig] = handle try: diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1660,12 +1660,12 @@ '.callback')) self.assertTrue(r.endswith('())'), r) - def test_make_handle(self): + def test_handle(self): def callback(*args): return args h1 = asyncio.Handle(callback, ()) self.assertRaises( - AssertionError, asyncio.events.make_handle, h1, ()) + AssertionError, asyncio.Handle, h1, ()) @unittest.mock.patch('asyncio.events.logger') def test_callback_with_exception(self, log): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 07:06:06 2014 From: python-checkins at python.org (larry.hastings) Date: Mon, 10 Feb 2014 07:06:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320517=3A_Function?= =?utf-8?q?s_in_the_os_module_that_accept_two_filenames?= Message-ID: <3fMxSZ3nvMz7LkQ@mail.python.org> http://hg.python.org/cpython/rev/081a9d8ba3c7 changeset: 89092:081a9d8ba3c7 user: Larry Hastings date: Sun Feb 09 22:05:19 2014 -0800 summary: Issue #20517: Functions in the os module that accept two filenames now register both filenames in the exception on failure. This required adding new C API functions allowing OSError exceptions to reference two filenames instead of one. files: Doc/c-api/exceptions.rst | 50 ++++++- Doc/data/refcounts.dat | 20 ++- Doc/library/exceptions.rst | 7 +- Include/pyerrors.h | 30 ++++ Lib/test/test_exceptions.py | 4 +- Lib/test/test_posix.py | 17 ++ Misc/NEWS | 12 + Modules/posixmodule.c | 25 ++- Objects/exceptions.c | 119 ++++++++++++---- Python/errors.c | 169 ++++++++++++++++++++--- 10 files changed, 380 insertions(+), 73 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -241,6 +241,15 @@ exception instance. +.. c:function:: PyObject* PyErr_SetFromErrnoWithFilenameObjects(PyObject *type, PyObject *filenameObject, PyObject *filenameObject2) + + Similar to :c:func:`PyErr_SetFromErrnoWithFilenameObject`, but takes a second + filename object, for raising errors when a function that takes two filenames + fails. + +.. versionadded:: 3.4 + + .. c:function:: PyObject* PyErr_SetFromErrnoWithFilename(PyObject *type, const char *filename) Similar to :c:func:`PyErr_SetFromErrnoWithFilenameObject`, but the filename @@ -248,6 +257,14 @@ (:func:`os.fsdecode`). +.. c:function:: PyObject* PyErr_SetFromErrnoWithFilenames(PyObject *type, const char *filename, const char *filename2) + + Similar to :c:func:`PyErr_SetFromErrnoWithFilename`, but accepts a + second filename. + +.. versionadded:: 3.4 + + .. c:function:: PyObject* PyErr_SetFromWindowsErr(int ierr) This is a convenience function to raise :exc:`WindowsError`. If called with @@ -266,13 +283,6 @@ specifying the exception type to be raised. Availability: Windows. -.. c:function:: PyObject* PyErr_SetFromWindowsErrWithFilenameObject(int ierr, PyObject *filenameObject) - - Similar to :c:func:`PyErr_SetFromWindowsErr`, with the additional behavior - that if *filenameObject* is not *NULL*, it is passed to the constructor of - :exc:`WindowsError` as a third parameter. Availability: Windows. - - .. c:function:: PyObject* PyErr_SetFromWindowsErrWithFilename(int ierr, const char *filename) Similar to :c:func:`PyErr_SetFromWindowsErrWithFilenameObject`, but the @@ -280,6 +290,14 @@ encoding (:func:`os.fsdecode`). Availability: Windows. +.. c:function:: PyObject* PyErr_SetFromWindowsErrWithFilenames(int ierr, const char *filename, const char *filename2) + + Similar to :c:func:`PyErr_SetFromWindowsErrWithFilename`, but accepts + a second filename. Availability: Windows. + +.. versionadded:: 3.4 + + .. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenameObject(PyObject *type, int ierr, PyObject *filename) Similar to :c:func:`PyErr_SetFromWindowsErrWithFilenameObject`, with an @@ -287,12 +305,30 @@ Availability: Windows. +.. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenameObjects(PyObject *type, int ierr, PyObject *filename, PyObject *filename2) + + Similar to :c:func:`PyErr_SetExcFromWindowsErrWithFilenameObject`, + but accepts a second filename object. + Availability: Windows. + +.. versionadded:: 3.4 + + .. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilename(PyObject *type, int ierr, const char *filename) Similar to :c:func:`PyErr_SetFromWindowsErrWithFilename`, with an additional parameter specifying the exception type to be raised. Availability: Windows. +.. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenames(PyObject *type, int ierr, const char *filename, const char *filename2) + + Similar to :c:func:`PyErr_SetExcFromWindowsErrWithFilename`, + but accepts a second filename object. + Availability: Windows. + +.. versionadded:: 3.4 + + .. c:function:: PyObject* PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) This is a convenience function to raise :exc:`ImportError`. *msg* will be diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -29,7 +29,7 @@ # reference to the item argument! # The parameter names are as they appear in the API manual, not the source -# code. +# code. PyBool_FromLong:PyObject*::+1: PyBool_FromLong:long:v:0: @@ -317,6 +317,12 @@ PyErr_SetExcFromWindowsErrWithFilename:int:ierr:: PyErr_SetExcFromWindowsErrWithFilename:const char*:filename:: +PyErr_SetExcFromWindowsErrWithFilenames:PyObject*::null: +PyErr_SetExcFromWindowsErrWithFilenames:PyObject*:type:0: +PyErr_SetExcFromWindowsErrWithFilenames:int:ierr:: +PyErr_SetExcFromWindowsErrWithFilenames:const char*:filename:: +PyErr_SetExcFromWindowsErrWithFilenames:const char*:filename2:: + PyErr_SetFromErrno:PyObject*::null: PyErr_SetFromErrno:PyObject*:type:0: @@ -324,6 +330,11 @@ PyErr_SetFromErrnoWithFilename:PyObject*:type:0: PyErr_SetFromErrnoWithFilename:const char*:filename:: +PyErr_SetFromErrnoWithFilenames:PyObject*::null: +PyErr_SetFromErrnoWithFilenames:PyObject*:type:0: +PyErr_SetFromErrnoWithFilenames:const char*:filename:: +PyErr_SetFromErrnoWithFilenames:const char*:filename2:: + PyErr_SetFromWindowsErr:PyObject*::null: PyErr_SetFromWindowsErr:int:ierr:: @@ -331,6 +342,11 @@ PyErr_SetFromWindowsErrWithFilename:int:ierr:: PyErr_SetFromWindowsErrWithFilename:const char*:filename:: +PyErr_SetFromWindowsErrWithFilenames:PyObject*::null: +PyErr_SetFromWindowsErrWithFilenames:int:ierr:: +PyErr_SetFromWindowsErrWithFilenames:const char*:filename:: +PyErr_SetFromWindowsErrWithFilenames:const char*:filename2:: + PyErr_SetInterrupt:void::: PyErr_SetNone:void::: @@ -907,7 +923,7 @@ PyNumber_Xor:PyObject*:o1:0: PyNumber_Xor:PyObject*:o2:0: -PyObject_AsFileDescriptor:int::: +PyObject_AsFileDescriptor:int::: PyObject_AsFileDescriptor:PyObject*:o:0: PyObject_Call:PyObject*::+1: diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -253,6 +253,11 @@ For exceptions that involve a file system path (such as :func:`open` or :func:`os.unlink`), the exception instance will contain an additional attribute, :attr:`filename`, which is the file name passed to the function. + For functions that involve two file system paths (such as + :func:`os.rename`), the exception instance will contain a second + :attr:`filename2` attribute corresponding to the second file name passed + to the function. + .. versionchanged:: 3.3 :exc:`EnvironmentError`, :exc:`IOError`, :exc:`WindowsError`, @@ -263,7 +268,7 @@ The :attr:`filename` attribute is now the original file name passed to the function, instead of the name encoded to or decoded from the - filesystem encoding. + filesystem encoding. Also, the :attr:`filename2` attribute was added. .. exception:: OverflowError diff --git a/Include/pyerrors.h b/Include/pyerrors.h --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -53,6 +53,7 @@ PyObject *myerrno; PyObject *strerror; PyObject *filename; + PyObject *filename2; #ifdef MS_WINDOWS PyObject *winerror; #endif @@ -225,13 +226,23 @@ PyAPI_FUNC(PyObject *) PyErr_SetFromErrno(PyObject *); PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenameObject( PyObject *, PyObject *); +PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenameObjects( + PyObject *, PyObject *, PyObject *); PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilename( PyObject *exc, const char *filename /* decoded from the filesystem encoding */ ); +PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenames( + PyObject *exc, + /* decoded from the filesystem encoding */ + const char *filename, + const char *filename2 + ); #if defined(MS_WINDOWS) && !defined(Py_LIMITED_API) PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilename( PyObject *, const Py_UNICODE *); +PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilenames( + PyObject *, const Py_UNICODE *, const Py_UNICODE *); #endif /* MS_WINDOWS */ PyAPI_FUNC(PyObject *) PyErr_Format( @@ -245,22 +256,41 @@ int ierr, const char *filename /* decoded from the filesystem encoding */ ); +PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilenames( + int ierr, + /* decoded from the filesystem encoding */ + const char *filename, + const char *filename2 + ); #ifndef Py_LIMITED_API /* XXX redeclare to use WSTRING */ PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilename( int, const Py_UNICODE *); +PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilenames( + int, const Py_UNICODE *, const Py_UNICODE *); #endif PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErr(int); PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenameObject( PyObject *,int, PyObject *); +PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenameObjects( + PyObject *,int, PyObject *, PyObject *); PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilename( PyObject *exc, int ierr, const char *filename /* decoded from the filesystem encoding */ ); +PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenames( + PyObject *exc, + int ierr, + /* decoded from the filesystem encoding */ + const char *filename, + const char *filename2 + ); #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilename( PyObject *,int, const Py_UNICODE *); +PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilenames( + PyObject *,int, const Py_UNICODE *, const Py_UNICODE *); #endif PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int); #endif /* MS_WINDOWS */ diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -266,8 +266,8 @@ (OSError, ('foo', 'bar', 'baz'), {'args' : ('foo', 'bar'), 'filename' : 'baz', 'errno' : 'foo', 'strerror' : 'bar'}), - (OSError, ('foo', 'bar', 'baz', 'quux'), - {'args' : ('foo', 'bar', 'baz', 'quux')}), + (OSError, ('foo', 'bar', 'baz', None, 'quux'), + {'args' : ('foo', 'bar'), 'filename' : 'baz', 'filename2': 'quux'}), (OSError, ('errnoStr', 'strErrorStr', 'filenameStr'), {'args' : ('errnoStr', 'strErrorStr'), 'strerror' : 'strErrorStr', 'errno' : 'errnoStr', diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1121,6 +1121,23 @@ # http://lists.freebsd.org/pipermail/freebsd-amd64/2012-January/014332.html raise unittest.SkipTest("OSError raised!") + def test_path_error2(self): + """ + Test functions that call path_error2(), providing two filenames in their exceptions. + """ + for name in ("rename", "replace", "link", "symlink"): + function = getattr(os, name, None) + + if function: + for dst in ("noodly2", support.TESTFN): + try: + function('doesnotexistfilename', dst) + except OSError as e: + self.assertIn("'doesnotexistfilename' -> '{}'".format(dst), str(e)) + break + else: + self.fail("No valid path_error2() test for os." + name) + class PosixGroupsTester(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,9 @@ Library ------- +- Issue #20517: Functions in the os module that accept two filenames + now register both filenames in the exception on failure. + - Issue #20563: The ipaddress module API is now considered stable. - Issue #14983: email.generator now always adds a line end after each MIME @@ -236,6 +239,15 @@ - Issue #20465: Update SQLite shipped with OS X installer to 3.8.3. +C-API +----- + +- Issue #20517: Added new functions allowing OSError exceptions to reference + two filenames instead of one: PyErr_SetFromErrnoWithFilenameObjects(), + PyErr_SetFromErrnoWithFilenames(), PyErr_SetFromWindowsErrWithFilenames(), + PyErr_SetExcFromWindowsErrWithFilenameObjects(), and + PyErr_SetExcFromWindowsErrWithFilenames(). + Documentation ------------- diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1313,6 +1313,19 @@ } +static PyObject * +path_error2(path_t *path, path_t *path2) +{ +#ifdef MS_WINDOWS + return PyErr_SetExcFromWindowsErrWithFilenameObjects(PyExc_OSError, + 0, path->object, path2->object); +#else + return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, + path->object, path2->object); +#endif +} + + /* POSIX generic methods */ static PyObject * @@ -3518,7 +3531,7 @@ Py_END_ALLOW_THREADS if (!result) { - return_value = path_error(&src); + return_value = path_error2(&src, &dst); goto exit; } #else @@ -3536,7 +3549,7 @@ Py_END_ALLOW_THREADS if (result) { - return_value = path_error(&src); + return_value = path_error2(&src, &dst); goto exit; } #endif @@ -4284,7 +4297,7 @@ Py_END_ALLOW_THREADS if (!result) { - return_value = path_error(&src); + return_value = path_error2(&src, &dst); goto exit; } @@ -4299,7 +4312,7 @@ Py_END_ALLOW_THREADS if (result) { - return_value = path_error(&src); + return_value = path_error2(&src, &dst); goto exit; } #endif @@ -7345,7 +7358,7 @@ Py_END_ALLOW_THREADS if (!result) { - return_value = path_error(&src); + return_value = path_error2(&src, &dst); goto exit; } @@ -7361,7 +7374,7 @@ Py_END_ALLOW_THREADS if (result) { - return_value = path_error(&src); + return_value = path_error2(&src, &dst); goto exit; } #endif diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -724,13 +724,17 @@ * we hack args so that it only contains two items. This also * means we need our own __str__() which prints out the filename * when it was supplied. + * + * (If a function has two filenames, such as rename(), symlink(), + * or copy(), PyErr_SetFromErrnoWithFilenames() is called, which + * allows passing in a second filename.) */ /* This function doesn't cleanup on error, the caller should */ static int oserror_parse_args(PyObject **p_args, PyObject **myerrno, PyObject **strerror, - PyObject **filename + PyObject **filename, PyObject **filename2 #ifdef MS_WINDOWS , PyObject **winerror #endif @@ -738,14 +742,23 @@ { Py_ssize_t nargs; PyObject *args = *p_args; +#ifndef MS_WINDOWS + /* + * ignored on non-Windows platforms, + * but parsed so OSError has a consistent signature + */ + PyObject *_winerror = NULL; + PyObject **winerror = &_winerror; +#endif /* MS_WINDOWS */ nargs = PyTuple_GET_SIZE(args); + if (nargs >= 2 && nargs <= 5) { + if (!PyArg_UnpackTuple(args, "OSError", 2, 5, + myerrno, strerror, + filename, winerror, filename2)) + return -1; #ifdef MS_WINDOWS - if (nargs >= 2 && nargs <= 4) { - if (!PyArg_UnpackTuple(args, "OSError", 2, 4, - myerrno, strerror, filename, winerror)) - return -1; if (*winerror && PyLong_Check(*winerror)) { long errcode, winerrcode; PyObject *newargs; @@ -777,14 +790,8 @@ Py_DECREF(args); args = *p_args = newargs; } +#endif /* MS_WINDOWS */ } -#else - if (nargs >= 2 && nargs <= 3) { - if (!PyArg_UnpackTuple(args, "OSError", 2, 3, - myerrno, strerror, filename)) - return -1; - } -#endif return 0; } @@ -792,7 +799,7 @@ static int oserror_init(PyOSErrorObject *self, PyObject **p_args, PyObject *myerrno, PyObject *strerror, - PyObject *filename + PyObject *filename, PyObject *filename2 #ifdef MS_WINDOWS , PyObject *winerror #endif @@ -816,9 +823,14 @@ Py_INCREF(filename); self->filename = filename; - if (nargs >= 2 && nargs <= 3) { - /* filename is removed from the args tuple (for compatibility - purposes, see test_exceptions.py) */ + if (filename2 && filename2 != Py_None) { + Py_INCREF(filename2); + self->filename2 = filename2; + } + + if (nargs >= 2 && nargs <= 5) { + /* filename, filename2, and winerror are removed from the args tuple + (for compatibility purposes, see test_exceptions.py) */ PyObject *subslice = PyTuple_GetSlice(args, 0, 2); if (!subslice) return -1; @@ -877,7 +889,8 @@ OSError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyOSErrorObject *self = NULL; - PyObject *myerrno = NULL, *strerror = NULL, *filename = NULL; + PyObject *myerrno = NULL, *strerror = NULL; + PyObject *filename = NULL, *filename2 = NULL; #ifdef MS_WINDOWS PyObject *winerror = NULL; #endif @@ -888,7 +901,8 @@ if (!_PyArg_NoKeywords(type->tp_name, kwds)) goto error; - if (oserror_parse_args(&args, &myerrno, &strerror, &filename + if (oserror_parse_args(&args, &myerrno, &strerror, + &filename, &filename2 #ifdef MS_WINDOWS , &winerror #endif @@ -917,7 +931,7 @@ self->written = -1; if (!oserror_use_init(type)) { - if (oserror_init(self, &args, myerrno, strerror, filename + if (oserror_init(self, &args, myerrno, strerror, filename, filename2 #ifdef MS_WINDOWS , winerror #endif @@ -942,7 +956,8 @@ static int OSError_init(PyOSErrorObject *self, PyObject *args, PyObject *kwds) { - PyObject *myerrno = NULL, *strerror = NULL, *filename = NULL; + PyObject *myerrno = NULL, *strerror = NULL; + PyObject *filename = NULL, *filename2 = NULL; #ifdef MS_WINDOWS PyObject *winerror = NULL; #endif @@ -955,14 +970,14 @@ return -1; Py_INCREF(args); - if (oserror_parse_args(&args, &myerrno, &strerror, &filename + if (oserror_parse_args(&args, &myerrno, &strerror, &filename, &filename2 #ifdef MS_WINDOWS , &winerror #endif )) goto error; - if (oserror_init(self, &args, myerrno, strerror, filename + if (oserror_init(self, &args, myerrno, strerror, filename, filename2 #ifdef MS_WINDOWS , winerror #endif @@ -982,6 +997,7 @@ Py_CLEAR(self->myerrno); Py_CLEAR(self->strerror); Py_CLEAR(self->filename); + Py_CLEAR(self->filename2); #ifdef MS_WINDOWS Py_CLEAR(self->winerror); #endif @@ -1003,6 +1019,7 @@ Py_VISIT(self->myerrno); Py_VISIT(self->strerror); Py_VISIT(self->filename); + Py_VISIT(self->filename2); #ifdef MS_WINDOWS Py_VISIT(self->winerror); #endif @@ -1012,23 +1029,42 @@ static PyObject * OSError_str(PyOSErrorObject *self) { +#define OR_NONE(x) ((x)?(x):Py_None) #ifdef MS_WINDOWS /* If available, winerror has the priority over myerrno */ - if (self->winerror && self->filename) - return PyUnicode_FromFormat("[WinError %S] %S: %R", - self->winerror ? self->winerror: Py_None, - self->strerror ? self->strerror: Py_None, - self->filename); + if (self->winerror && self->filename) { + if (self->filename2) { + return PyUnicode_FromFormat("[WinError %S] %S: %R -> %R", + OR_NONE(self->winerror), + OR_NONE(self->strerror), + self->filename, + self->filename2); + } else { + return PyUnicode_FromFormat("[WinError %S] %S: %R", + OR_NONE(self->winerror), + OR_NONE(self->strerror), + self->filename); + } + } if (self->winerror && self->strerror) return PyUnicode_FromFormat("[WinError %S] %S", self->winerror ? self->winerror: Py_None, self->strerror ? self->strerror: Py_None); #endif - if (self->filename) - return PyUnicode_FromFormat("[Errno %S] %S: %R", - self->myerrno ? self->myerrno: Py_None, - self->strerror ? self->strerror: Py_None, - self->filename); + if (self->filename) { + if (self->filename2) { + return PyUnicode_FromFormat("[Errno %S] %S: %R -> %R", + OR_NONE(self->myerrno), + OR_NONE(self->strerror), + self->filename, + self->filename2); + } else { + return PyUnicode_FromFormat("[Errno %S] %S: %R", + OR_NONE(self->myerrno), + OR_NONE(self->strerror), + self->filename); + } + } if (self->myerrno && self->strerror) return PyUnicode_FromFormat("[Errno %S] %S", self->myerrno ? self->myerrno: Py_None, @@ -1045,7 +1081,8 @@ /* self->args is only the first two real arguments if there was a * file name given to OSError. */ if (PyTuple_GET_SIZE(args) == 2 && self->filename) { - args = PyTuple_New(3); + Py_ssize_t size = self->filename2 ? 5 : 3; + args = PyTuple_New(size); if (!args) return NULL; @@ -1059,6 +1096,20 @@ Py_INCREF(self->filename); PyTuple_SET_ITEM(args, 2, self->filename); + + if (self->filename2) { + /* + * This tuple is essentially used as OSError(*args). + * So, to recreate filename2, we need to pass in + * winerror as well. + */ + Py_INCREF(Py_None); + PyTuple_SET_ITEM(args, 3, Py_None); + + /* filename2 */ + Py_INCREF(self->filename2); + PyTuple_SET_ITEM(args, 4, self->filename2); + } } else Py_INCREF(args); @@ -1098,6 +1149,8 @@ PyDoc_STR("exception strerror")}, {"filename", T_OBJECT, offsetof(PyOSErrorObject, filename), 0, PyDoc_STR("exception filename")}, + {"filename2", T_OBJECT, offsetof(PyOSErrorObject, filename2), 0, + PyDoc_STR("second exception filename")}, #ifdef MS_WINDOWS {"winerror", T_OBJECT, offsetof(PyOSErrorObject, winerror), 0, PyDoc_STR("Win32 exception code")}, diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -410,6 +410,12 @@ PyObject * PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject) { + return PyErr_SetFromErrnoWithFilenameObjects(exc, filenameObject, NULL); +} + +PyObject * +PyErr_SetFromErrnoWithFilenameObjects(PyObject *exc, PyObject *filenameObject, PyObject *filenameObject2) +{ PyObject *message; PyObject *v, *args; int i = errno; @@ -480,10 +486,15 @@ return NULL; } - if (filenameObject != NULL) - args = Py_BuildValue("(iOO)", i, message, filenameObject); - else + if (filenameObject != NULL) { + if (filenameObject2 != NULL) + args = Py_BuildValue("(iOOiO)", i, message, filenameObject, 0, filenameObject2); + else + args = Py_BuildValue("(iOO)", i, message, filenameObject); + } else { + assert(filenameObject2 == NULL); args = Py_BuildValue("(iO)", i, message); + } Py_DECREF(message); if (args != NULL) { @@ -500,16 +511,26 @@ return NULL; } - PyObject * PyErr_SetFromErrnoWithFilename(PyObject *exc, const char *filename) { PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; - PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); + PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, NULL); Py_XDECREF(name); return result; } +PyObject * +PyErr_SetFromErrnoWithFilenames(PyObject *exc, const char *filename, const char *filename2) +{ + PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; + PyObject *name2 = filename2 ? PyUnicode_DecodeFSDefault(filename2) : NULL; + PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, name2); + Py_XDECREF(name); + Py_XDECREF(name2); + return result; +} + #ifdef MS_WINDOWS PyObject * PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, const Py_UNICODE *filename) @@ -517,16 +538,31 @@ PyObject *name = filename ? PyUnicode_FromUnicode(filename, wcslen(filename)) : NULL; - PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); + PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, NULL); Py_XDECREF(name); return result; } + +PyObject * +PyErr_SetFromErrnoWithUnicodeFilenames(PyObject *exc, const Py_UNICODE *filename, const Py_UNICODE *filename2) +{ + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *name2 = filename2 ? + PyUnicode_FromUnicode(filename2, wcslen(filename2)) : + NULL; + PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, name2); + Py_XDECREF(name); + Py_XDECREF(name2); + return result; +} #endif /* MS_WINDOWS */ PyObject * PyErr_SetFromErrno(PyObject *exc) { - return PyErr_SetFromErrnoWithFilenameObject(exc, NULL); + return PyErr_SetFromErrnoWithFilenameObjects(exc, NULL, NULL); } #ifdef MS_WINDOWS @@ -536,6 +572,16 @@ int ierr, PyObject *filenameObject) { + return PyErr_SetExcFromWindowsErrWithFilenameObjects(exc, ierr, + filenameObject, NULL); +} + +PyObject *PyErr_SetExcFromWindowsErrWithFilenameObjects( + PyObject *exc, + int ierr, + PyObject *filenameObject, + PyObject *filenameObject2) +{ int len; WCHAR *s_buf = NULL; /* Free via LocalFree */ PyObject *message; @@ -571,11 +617,15 @@ return NULL; } - if (filenameObject == NULL) - filenameObject = Py_None; - /* This is the constructor signature for passing a Windows error code. + if (filenameObject == NULL) { + assert(filenameObject2 == NULL); + filenameObject = filenameObject2 = Py_None; + } + else if (filenameObject2 == NULL) + filenameObject2 = Py_None; + /* This is the constructor signature for OSError. The POSIX translation will be figured out by the constructor. */ - args = Py_BuildValue("(iOOi)", 0, message, filenameObject, err); + args = Py_BuildValue("(iOOiO)", 0, message, filenameObject, err, filenameObject2); Py_DECREF(message); if (args != NULL) { @@ -596,13 +646,31 @@ const char *filename) { PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; - PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc, ierr, - name); + name, + NULL); Py_XDECREF(name); return ret; } +PyObject *PyErr_SetExcFromWindowsErrWithFilenames( + PyObject *exc, + int ierr, + const char *filename, + const char *filename2) +{ + PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; + PyObject *name2 = filename2 ? PyUnicode_DecodeFSDefault(filename2) : NULL; + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc, + ierr, + name, + name2); + Py_XDECREF(name); + Py_XDECREF(name2); + return ret; +} + PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename( PyObject *exc, int ierr, @@ -611,31 +679,69 @@ PyObject *name = filename ? PyUnicode_FromUnicode(filename, wcslen(filename)) : NULL; - PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc, ierr, - name); + name, + NULL); Py_XDECREF(name); return ret; } +PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilenames( + PyObject *exc, + int ierr, + const Py_UNICODE *filename, + const Py_UNICODE *filename2) +{ + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *name2 = filename2 ? + PyUnicode_FromUnicode(filename2, wcslen(filename2)) : + NULL; + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc, + ierr, + name, + name2); + Py_XDECREF(name); + Py_XDECREF(name2); + return ret; +} + PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr) { - return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL); + return PyErr_SetExcFromWindowsErrWithFilenames(exc, ierr, NULL, NULL); } PyObject *PyErr_SetFromWindowsErr(int ierr) { - return PyErr_SetExcFromWindowsErrWithFilename(PyExc_OSError, - ierr, NULL); + return PyErr_SetExcFromWindowsErrWithFilenames(PyExc_OSError, + ierr, NULL, NULL); } + +PyObject *PyErr_SetFromWindowsErrWithFilenames( + int ierr, + const char *filename, + const char *filename2) +{ + PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; + PyObject *name2 = filename2 ? PyUnicode_DecodeFSDefault(filename2) : NULL; + PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects( + PyExc_OSError, + ierr, name, name2); + Py_XDECREF(name); + Py_XDECREF(name2); + return result; +} + PyObject *PyErr_SetFromWindowsErrWithFilename( int ierr, const char *filename) { PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; - PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( + PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects( PyExc_OSError, - ierr, name); + ierr, name, NULL); Py_XDECREF(name); return result; } @@ -647,12 +753,31 @@ PyObject *name = filename ? PyUnicode_FromUnicode(filename, wcslen(filename)) : NULL; - PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( + PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects( PyExc_OSError, - ierr, name); + ierr, name, NULL); Py_XDECREF(name); return result; } + +PyObject *PyErr_SetFromWindowsErrWithUnicodeFilenames( + int ierr, + const Py_UNICODE *filename, + const Py_UNICODE *filename2) +{ + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : + NULL; + PyObject *name2 = filename2 ? + PyUnicode_FromUnicode(filename2, wcslen(filename2)) : + NULL; + PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects( + PyExc_OSError, + ierr, name, name2); + Py_XDECREF(name); + Py_XDECREF(name2); + return result; +} #endif /* MS_WINDOWS */ PyObject * -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 07:23:22 2014 From: python-checkins at python.org (larry.hastings) Date: Mon, 10 Feb 2014 07:23:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320530=3A_The_sign?= =?utf-8?q?atures_for_slot_builtins_have_been_updated?= Message-ID: <3fMxrV2Gl4z7LkW@mail.python.org> http://hg.python.org/cpython/rev/28aef6e22736 changeset: 89093:28aef6e22736 user: Larry Hastings date: Sun Feb 09 22:22:38 2014 -0800 summary: Issue #20530: The signatures for slot builtins have been updated to reflect the fact that they only accept positional-only arguments. files: Misc/NEWS | 3 + Objects/typeobject.c | 84 ++++++++++++++++---------------- 2 files changed, 45 insertions(+), 42 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,9 @@ Library ------- +- Issue #20530: The signatures for slot builtins have been updated + to reflect the fact that they only accept positional-only arguments. + - Issue #20517: Functions in the os module that accept two filenames now register both filenames in the exception on failure. diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6134,22 +6134,22 @@ ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, DOC) #define UNSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \ - NAME "($self)\n--\n\n" DOC) + NAME "($self, /)\n--\n\n" DOC) #define IBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \ - NAME "($self, value)\n--\n\nReturn self" DOC "value.") + NAME "($self, value, /)\n--\n\nReturn self" DOC "value.") #define BINSLOT(NAME, SLOT, FUNCTION, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \ - NAME "($self, value)\n--\n\nReturn self" DOC "value.") + NAME "($self, value, /)\n--\n\nReturn self" DOC "value.") #define RBINSLOT(NAME, SLOT, FUNCTION, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \ - NAME "($self, value)\n--\n\nReturn value" DOC "self.") + NAME "($self, value, /)\n--\n\nReturn value" DOC "self.") #define BINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \ - NAME "($self, value)\n--\n\n" DOC) + NAME "($self, value, /)\n--\n\n" DOC) #define RBINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \ ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \ - NAME "($self, value)\n--\n\n" DOC) + NAME "($self, value, /)\n--\n\n" DOC) static slotdef slotdefs[] = { TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""), @@ -6157,51 +6157,51 @@ TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""), TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""), TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc, - "__repr__($self)\n--\n\nReturn repr(self)."), + "__repr__($self, /)\n--\n\nReturn repr(self)."), TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc, - "__hash__($self)\n--\n\nReturn hash(self)."), + "__hash__($self, /)\n--\n\nReturn hash(self)."), FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call, - "__call__($self, *args, **kwargs)\n--\n\nCall self as a function.", + "__call__($self, /, *args, **kwargs)\n--\n\nCall self as a function.", PyWrapperFlag_KEYWORDS), TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc, - "__str__($self)\n--\n\nReturn str(self)."), + "__str__($self, /)\n--\n\nReturn str(self)."), TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook, wrap_binaryfunc, - "__getattribute__($self, name)\n--\n\nReturn getattr(self, name)."), + "__getattribute__($self, name, /)\n--\n\nReturn getattr(self, name)."), TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""), TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr, - "__setattr__($self, name, value)\n--\n\nImplement setattr(self, name, value)."), + "__setattr__($self, name, value, /)\n--\n\nImplement setattr(self, name, value)."), TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr, - "__delattr__($self, name)\n--\n\nImplement delattr(self, name)."), + "__delattr__($self, name, /)\n--\n\nImplement delattr(self, name)."), TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt, - "__lt__($self, value)\n--\n\nReturn selfvalue."), + "__gt__($self, value, /)\n--\n\nReturn self>value."), TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge, - "__ge__=($self, value)\n--\n\nReturn self>=value."), + "__ge__=($self, value, /)\n--\n\nReturn self>=value."), TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc, - "__iter__($self)\n--\n\nImplement iter(self)."), + "__iter__($self, /)\n--\n\nImplement iter(self)."), TPSLOT("__next__", tp_iternext, slot_tp_iternext, wrap_next, - "__next__($self)\n--\n\nImplement next(self)."), + "__next__($self, /)\n--\n\nImplement next(self)."), TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get, - "__get__($self, instance, owner)\n--\n\nReturn an attribute of instance, which is of type owner."), + "__get__($self, instance, owner, /)\n--\n\nReturn an attribute of instance, which is of type owner."), TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set, - "__set__($self, instance, value)\n--\n\nSet an attribute of instance to value."), + "__set__($self, instance, value, /)\n--\n\nSet an attribute of instance to value."), TPSLOT("__delete__", tp_descr_set, slot_tp_descr_set, wrap_descr_delete, - "__delete__(instance)\n--\n\nDelete an attribute of instance."), + "__delete__(instance, /)\n--\n\nDelete an attribute of instance."), FLSLOT("__init__", tp_init, slot_tp_init, (wrapperfunc)wrap_init, - "__init__($self, *args, **kwargs)\n--\n\n" + "__init__($self, /, *args, **kwargs)\n--\n\n" "Initialize self. See help(type(self)) for accurate signature.", PyWrapperFlag_KEYWORDS), TPSLOT("__new__", tp_new, slot_tp_new, NULL, - "__new__(type, *args, **kwargs)\n--\n\n" + "__new__(type, /, *args, **kwargs)\n--\n\n" "Create and return new object. See help(type) for accurate signature."), TPSLOT("__del__", tp_finalize, slot_tp_finalize, (wrapperfunc)wrap_del, ""), @@ -6226,9 +6226,9 @@ RBINSLOTNOTINFIX("__rdivmod__", nb_divmod, slot_nb_divmod, "Return divmod(value, self)."), NBSLOT("__pow__", nb_power, slot_nb_power, wrap_ternaryfunc, - "__pow__($self, value, mod=None)\n--\n\nReturn pow(self, value, mod)."), + "__pow__($self, value, mod=None, /)\n--\n\nReturn pow(self, value, mod)."), NBSLOT("__rpow__", nb_power, slot_nb_power, wrap_ternaryfunc_r, - "__rpow__($self, value, mod=None)\n--\n\nReturn pow(value, self, mod)."), + "__rpow__($self, value, mod=None, /)\n--\n\nReturn pow(value, self, mod)."), UNSLOT("__neg__", nb_negative, slot_nb_negative, wrap_unaryfunc, "-self"), UNSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc, "+self"), UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc, @@ -6279,48 +6279,48 @@ IBSLOT("__itruediv__", nb_inplace_true_divide, slot_nb_inplace_true_divide, wrap_binaryfunc, "/"), NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc, - "__index__($self)\n--\n\n" + "__index__($self, /)\n--\n\n" "Return self converted to an integer, if self is suitable" "for use as an index into a list."), MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc, - "__len__($self)\n--\n\nReturn len(self)."), + "__len__($self, /)\n--\n\nReturn len(self)."), MPSLOT("__getitem__", mp_subscript, slot_mp_subscript, wrap_binaryfunc, - "__getitem__($self, key)\n--\n\nReturn self[key]."), + "__getitem__($self, key, /)\n--\n\nReturn self[key]."), MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript, wrap_objobjargproc, - "__setitem__($self, key, value)\n--\n\nSet self[key] to value."), + "__setitem__($self, key, value, /)\n--\n\nSet self[key] to value."), MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript, wrap_delitem, "__delitem__(key)\n--\n\nDelete self[key]."), SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc, - "__len__($self)\n--\n\nReturn len(self)."), + "__len__($self, /)\n--\n\nReturn len(self)."), /* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL. The logic in abstract.c always falls back to nb_add/nb_multiply in this case. Defining both the nb_* and the sq_* slots to call the user-defined methods has unexpected side-effects, as shown by test_descr.notimplemented() */ SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc, - "__add__($self, value)\n--\n\nReturn self+value."), + "__add__($self, value, /)\n--\n\nReturn self+value."), SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, - "__mul__($self, value)\n--\n\nReturn self*value.n"), + "__mul__($self, value, /)\n--\n\nReturn self*value.n"), SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, - "__rmul__($self, value)\n--\n\nReturn self*value."), + "__rmul__($self, value, /)\n--\n\nReturn self*value."), SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, - "__getitem__($self, key)\n--\n\nReturn self[key]."), + "__getitem__($self, key, /)\n--\n\nReturn self[key]."), SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem, - "__setitem__($self, key, value)\n--\n\nSet self[key] to value."), + "__setitem__($self, key, value, /)\n--\n\nSet self[key] to value."), SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem, - "__delitem__($self, key)\n--\n\nDelete self[key]."), + "__delitem__($self, key, /)\n--\n\nDelete self[key]."), SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc, - "__contains__($self, key)\n--\n\nReturn key in self."), + "__contains__($self, key, /)\n--\n\nReturn key in self."), SQSLOT("__iadd__", sq_inplace_concat, NULL, wrap_binaryfunc, - "__iadd__($self, value)\n--\n\nImplement self+=value."), + "__iadd__($self, value, /)\n--\n\nImplement self+=value."), SQSLOT("__imul__", sq_inplace_repeat, NULL, wrap_indexargfunc, - "__imul__($self, value)\n--\n\nImplement self*=value."), + "__imul__($self, value, /)\n--\n\nImplement self*=value."), {NULL} }; -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Feb 10 08:15:44 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 10 Feb 2014 08:15:44 +0100 Subject: [Python-checkins] Daily reference leaks (aa7ce6f74303): sum=0 Message-ID: results for aa7ce6f74303 on branch "default" -------------------------------------------- test_site leaked [-2, 0, 2] references, sum=0 test_site leaked [-2, 0, 2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog5PIMo0', '-x'] From python-checkins at python.org Mon Feb 10 08:59:18 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 10 Feb 2014 08:59:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE5OTA2OiBjbGFy?= =?utf-8?q?ify_note_in_urllib_docs=2E?= Message-ID: <3fMzzB31ZKz7LkP@mail.python.org> http://hg.python.org/cpython/rev/2ac7551986ba changeset: 89094:2ac7551986ba branch: 2.7 parent: 89084:6b10943a5916 user: Ezio Melotti date: Mon Feb 10 09:59:04 2014 +0200 summary: #19906: clarify note in urllib docs. files: Doc/library/urllib.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/urllib.rst b/Doc/library/urllib.rst --- a/Doc/library/urllib.rst +++ b/Doc/library/urllib.rst @@ -9,8 +9,9 @@ Python 3 to :mod:`urllib.request`, :mod:`urllib.parse`, and :mod:`urllib.error`. The :term:`2to3` tool will automatically adapt imports when converting your sources to Python 3. - Also note that the :func:`urllib.urlopen` function has been removed in - Python 3 in favor of :func:`urllib2.urlopen`. + Also note that the :func:`urllib.request.urlopen` function in Python 3 is + equivalent to :func:`urllib2.urlopen` and that :func:`urllib.urlopen` has + been removed. .. index:: single: WWW -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 09:29:01 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 10 Feb 2014 09:29:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_=2312296=3A_clarify_parag?= =?utf-8?q?raph_about_backward-compatibility=2E__Patch_by_Moritz_Neeb=2C?= Message-ID: <3fN0dT4zjlz7LjN@mail.python.org> http://hg.python.org/devguide/rev/4ce6bfb27267 changeset: 665:4ce6bfb27267 user: Ezio Melotti date: Mon Feb 10 10:28:49 2014 +0200 summary: #12296: clarify paragraph about backward-compatibility. Patch by Moritz Neeb, Jyrki Pulliainen, and ?ric Araujo. files: patch.rst | 15 +++++++++------ 1 files changed, 9 insertions(+), 6 deletions(-) diff --git a/patch.rst b/patch.rst --- a/patch.rst +++ b/patch.rst @@ -55,13 +55,16 @@ Second, be aware of backwards-compatibility considerations. While the core developer who eventually handles your patch will make the final call on whether -something is acceptable, having you think about backwards-compatibility early -will help prevent having your patch rejected on these grounds. Basically just -put yourself in the shoes of someone whose code will be broken by a change to -pre-existing semantics. It is guaranteed that any change made **will** break +something is acceptable, thinking about backwards-compatibility early +will help prevent having your patch rejected on these grounds. Put yourself in +the shoes of someone whose code will be broken by the change(s) introduced by +the patch. It is quite likely that any change made will break someone's code, so you need to have a good reason to make a change as you will -be forcing someone somewhere to update their code (this obviously does not apply -to new semantics). +be forcing someone to update their code. (This obviously does not apply to new +classes or functions; new arguments should be optional and have default values +which maintain the existing behavior.) If in doubt, have a look at +:PEP:`387` or :ref:`discuss ` the issue with experienced +developers. Third, make sure you have proper tests to verify your patch works as expected. Patches will not be accepted without the proper tests! -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Mon Feb 10 11:48:24 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 10 Feb 2014 11:48:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320505=3A_Add_debu?= =?utf-8?q?g_info_to_analyze_sporaric_failures_of?= Message-ID: <3fN3kJ747bzSqw@mail.python.org> http://hg.python.org/cpython/rev/32dc137f5e26 changeset: 89095:32dc137f5e26 parent: 89093:28aef6e22736 user: Victor Stinner date: Mon Feb 10 11:47:50 2014 +0100 summary: Issue #20505: Add debug info to analyze sporaric failures of test_timeout_rounding() on Windows XP buildbots. files: Lib/asyncio/base_events.py | 6 ++++++ Lib/test/test_asyncio/test_events.py | 5 ++++- 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -633,7 +633,13 @@ else: logger.log(level, 'poll took %.3f seconds', t1-t0) else: + t0 = self.time() event_list = self._selector.select(timeout) + dt = self.time() - t0 + if not event_list and timeout and dt < timeout: + print("asyncio: selector.select(%.3f ms) took %.3f ms" + % (timeout*1e3, dt*1e3), + file=sys.__stderr__, flush=True) self._process_events(event_list) # Handle 'later' callbacks that are ready. diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1182,7 +1182,10 @@ # may sleep at little bit less than timeout depending on the resolution # of the clock used by the kernel. Tolerate 2 useless calls on these # platforms. - self.assertLessEqual(self.loop._run_once_counter, 8) + self.assertLessEqual(self.loop._run_once_counter, 8, + {'time_info': time.get_clock_info('time'), + 'monotonic_info': time.get_clock_info('monotonic'), + 'selector': self.loop._selector.__class__.__name__}) class SubprocessTestsMixin: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 13:16:55 2014 From: python-checkins at python.org (larry.hastings) Date: Mon, 10 Feb 2014 13:16:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320517=3A_Removed_?= =?utf-8?q?unnecessary_new_=28short-lived=29_functions_from_PyErr=2E?= Message-ID: <3fN5hR5DsSz7LjM@mail.python.org> http://hg.python.org/cpython/rev/6343bdbb7085 changeset: 89096:6343bdbb7085 user: Larry Hastings date: Mon Feb 10 03:43:57 2014 -0800 summary: Issue #20517: Removed unnecessary new (short-lived) functions from PyErr. files: Doc/c-api/exceptions.rst | 25 ------ Doc/data/refcounts.dat | 16 ---- Include/pyerrors.h | 25 ------ Misc/NEWS | 6 +- Objects/exceptions.c | 4 +- Python/errors.c | 104 +-------------------------- 6 files changed, 7 insertions(+), 173 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -257,14 +257,6 @@ (:func:`os.fsdecode`). -.. c:function:: PyObject* PyErr_SetFromErrnoWithFilenames(PyObject *type, const char *filename, const char *filename2) - - Similar to :c:func:`PyErr_SetFromErrnoWithFilename`, but accepts a - second filename. - -.. versionadded:: 3.4 - - .. c:function:: PyObject* PyErr_SetFromWindowsErr(int ierr) This is a convenience function to raise :exc:`WindowsError`. If called with @@ -290,14 +282,6 @@ encoding (:func:`os.fsdecode`). Availability: Windows. -.. c:function:: PyObject* PyErr_SetFromWindowsErrWithFilenames(int ierr, const char *filename, const char *filename2) - - Similar to :c:func:`PyErr_SetFromWindowsErrWithFilename`, but accepts - a second filename. Availability: Windows. - -.. versionadded:: 3.4 - - .. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenameObject(PyObject *type, int ierr, PyObject *filename) Similar to :c:func:`PyErr_SetFromWindowsErrWithFilenameObject`, with an @@ -320,15 +304,6 @@ parameter specifying the exception type to be raised. Availability: Windows. -.. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenames(PyObject *type, int ierr, const char *filename, const char *filename2) - - Similar to :c:func:`PyErr_SetExcFromWindowsErrWithFilename`, - but accepts a second filename object. - Availability: Windows. - -.. versionadded:: 3.4 - - .. c:function:: PyObject* PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path) This is a convenience function to raise :exc:`ImportError`. *msg* will be diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -317,12 +317,6 @@ PyErr_SetExcFromWindowsErrWithFilename:int:ierr:: PyErr_SetExcFromWindowsErrWithFilename:const char*:filename:: -PyErr_SetExcFromWindowsErrWithFilenames:PyObject*::null: -PyErr_SetExcFromWindowsErrWithFilenames:PyObject*:type:0: -PyErr_SetExcFromWindowsErrWithFilenames:int:ierr:: -PyErr_SetExcFromWindowsErrWithFilenames:const char*:filename:: -PyErr_SetExcFromWindowsErrWithFilenames:const char*:filename2:: - PyErr_SetFromErrno:PyObject*::null: PyErr_SetFromErrno:PyObject*:type:0: @@ -330,11 +324,6 @@ PyErr_SetFromErrnoWithFilename:PyObject*:type:0: PyErr_SetFromErrnoWithFilename:const char*:filename:: -PyErr_SetFromErrnoWithFilenames:PyObject*::null: -PyErr_SetFromErrnoWithFilenames:PyObject*:type:0: -PyErr_SetFromErrnoWithFilenames:const char*:filename:: -PyErr_SetFromErrnoWithFilenames:const char*:filename2:: - PyErr_SetFromWindowsErr:PyObject*::null: PyErr_SetFromWindowsErr:int:ierr:: @@ -342,11 +331,6 @@ PyErr_SetFromWindowsErrWithFilename:int:ierr:: PyErr_SetFromWindowsErrWithFilename:const char*:filename:: -PyErr_SetFromWindowsErrWithFilenames:PyObject*::null: -PyErr_SetFromWindowsErrWithFilenames:int:ierr:: -PyErr_SetFromWindowsErrWithFilenames:const char*:filename:: -PyErr_SetFromWindowsErrWithFilenames:const char*:filename2:: - PyErr_SetInterrupt:void::: PyErr_SetNone:void::: diff --git a/Include/pyerrors.h b/Include/pyerrors.h --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -232,17 +232,9 @@ PyObject *exc, const char *filename /* decoded from the filesystem encoding */ ); -PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenames( - PyObject *exc, - /* decoded from the filesystem encoding */ - const char *filename, - const char *filename2 - ); #if defined(MS_WINDOWS) && !defined(Py_LIMITED_API) PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilename( PyObject *, const Py_UNICODE *); -PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilenames( - PyObject *, const Py_UNICODE *, const Py_UNICODE *); #endif /* MS_WINDOWS */ PyAPI_FUNC(PyObject *) PyErr_Format( @@ -256,18 +248,10 @@ int ierr, const char *filename /* decoded from the filesystem encoding */ ); -PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilenames( - int ierr, - /* decoded from the filesystem encoding */ - const char *filename, - const char *filename2 - ); #ifndef Py_LIMITED_API /* XXX redeclare to use WSTRING */ PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilename( int, const Py_UNICODE *); -PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilenames( - int, const Py_UNICODE *, const Py_UNICODE *); #endif PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErr(int); PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenameObject( @@ -279,18 +263,9 @@ int ierr, const char *filename /* decoded from the filesystem encoding */ ); -PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenames( - PyObject *exc, - int ierr, - /* decoded from the filesystem encoding */ - const char *filename, - const char *filename2 - ); #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilename( PyObject *,int, const Py_UNICODE *); -PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilenames( - PyObject *,int, const Py_UNICODE *, const Py_UNICODE *); #endif PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int); #endif /* MS_WINDOWS */ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -246,10 +246,8 @@ ----- - Issue #20517: Added new functions allowing OSError exceptions to reference - two filenames instead of one: PyErr_SetFromErrnoWithFilenameObjects(), - PyErr_SetFromErrnoWithFilenames(), PyErr_SetFromWindowsErrWithFilenames(), - PyErr_SetExcFromWindowsErrWithFilenameObjects(), and - PyErr_SetExcFromWindowsErrWithFilenames(). + two filenames instead of one: PyErr_SetFromErrnoWithFilenameObjects() and + PyErr_SetExcFromWindowsErrWithFilenameObjects(). Documentation ------------- diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -726,8 +726,8 @@ * when it was supplied. * * (If a function has two filenames, such as rename(), symlink(), - * or copy(), PyErr_SetFromErrnoWithFilenames() is called, which - * allows passing in a second filename.) + * or copy(), PyErr_SetFromErrnoWithFilenameObjects() is called, + * which allows passing in a second filename.) */ /* This function doesn't cleanup on error, the caller should */ diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -520,17 +520,6 @@ return result; } -PyObject * -PyErr_SetFromErrnoWithFilenames(PyObject *exc, const char *filename, const char *filename2) -{ - PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; - PyObject *name2 = filename2 ? PyUnicode_DecodeFSDefault(filename2) : NULL; - PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, name2); - Py_XDECREF(name); - Py_XDECREF(name2); - return result; -} - #ifdef MS_WINDOWS PyObject * PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, const Py_UNICODE *filename) @@ -542,21 +531,6 @@ Py_XDECREF(name); return result; } - -PyObject * -PyErr_SetFromErrnoWithUnicodeFilenames(PyObject *exc, const Py_UNICODE *filename, const Py_UNICODE *filename2) -{ - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : - NULL; - PyObject *name2 = filename2 ? - PyUnicode_FromUnicode(filename2, wcslen(filename2)) : - NULL; - PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, name2); - Py_XDECREF(name); - Py_XDECREF(name2); - return result; -} #endif /* MS_WINDOWS */ PyObject * @@ -654,23 +628,6 @@ return ret; } -PyObject *PyErr_SetExcFromWindowsErrWithFilenames( - PyObject *exc, - int ierr, - const char *filename, - const char *filename2) -{ - PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; - PyObject *name2 = filename2 ? PyUnicode_DecodeFSDefault(filename2) : NULL; - PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc, - ierr, - name, - name2); - Py_XDECREF(name); - Py_XDECREF(name2); - return ret; -} - PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename( PyObject *exc, int ierr, @@ -687,51 +644,15 @@ return ret; } -PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilenames( - PyObject *exc, - int ierr, - const Py_UNICODE *filename, - const Py_UNICODE *filename2) -{ - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : - NULL; - PyObject *name2 = filename2 ? - PyUnicode_FromUnicode(filename2, wcslen(filename2)) : - NULL; - PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc, - ierr, - name, - name2); - Py_XDECREF(name); - Py_XDECREF(name2); - return ret; -} - PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr) { - return PyErr_SetExcFromWindowsErrWithFilenames(exc, ierr, NULL, NULL); + return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL); } PyObject *PyErr_SetFromWindowsErr(int ierr) { - return PyErr_SetExcFromWindowsErrWithFilenames(PyExc_OSError, - ierr, NULL, NULL); -} - -PyObject *PyErr_SetFromWindowsErrWithFilenames( - int ierr, - const char *filename, - const char *filename2) -{ - PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL; - PyObject *name2 = filename2 ? PyUnicode_DecodeFSDefault(filename2) : NULL; - PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects( - PyExc_OSError, - ierr, name, name2); - Py_XDECREF(name); - Py_XDECREF(name2); - return result; + return PyErr_SetExcFromWindowsErrWithFilename(PyExc_OSError, + ierr, NULL); } PyObject *PyErr_SetFromWindowsErrWithFilename( @@ -759,25 +680,6 @@ Py_XDECREF(name); return result; } - -PyObject *PyErr_SetFromWindowsErrWithUnicodeFilenames( - int ierr, - const Py_UNICODE *filename, - const Py_UNICODE *filename2) -{ - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : - NULL; - PyObject *name2 = filename2 ? - PyUnicode_FromUnicode(filename2, wcslen(filename2)) : - NULL; - PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects( - PyExc_OSError, - ierr, name, name2); - Py_XDECREF(name); - Py_XDECREF(name2); - return result; -} #endif /* MS_WINDOWS */ PyObject * -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 17:21:58 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 10 Feb 2014 17:21:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2319255=3A_The_buil?= =?utf-8?q?tins_module_is_restored_to_initial_value_before?= Message-ID: <3fNC7B50KYz7LjM@mail.python.org> http://hg.python.org/cpython/rev/6a1711c96fa6 changeset: 89097:6a1711c96fa6 user: Serhiy Storchaka date: Mon Feb 10 18:21:34 2014 +0200 summary: Issue #19255: The builtins module is restored to initial value before cleaning other modules. The sys and builtins modules are cleaned last. files: Include/moduleobject.h | 1 + Include/pystate.h | 2 +- Lib/test/test_builtin.py | 29 +++++++++ Misc/NEWS | 3 + Objects/moduleobject.c | 13 ++- Python/import.c | 85 +++++++++++++++++---------- Python/pystate.c | 2 + 7 files changed, 96 insertions(+), 39 deletions(-) diff --git a/Include/moduleobject.h b/Include/moduleobject.h --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -25,6 +25,7 @@ PyAPI_FUNC(PyObject *) PyModule_GetFilenameObject(PyObject *); #ifndef Py_LIMITED_API PyAPI_FUNC(void) _PyModule_Clear(PyObject *); +PyAPI_FUNC(void) _PyModule_ClearDict(PyObject *); #endif PyAPI_FUNC(struct PyModuleDef*) PyModule_GetDef(PyObject*); PyAPI_FUNC(void*) PyModule_GetState(PyObject*); diff --git a/Include/pystate.h b/Include/pystate.h --- a/Include/pystate.h +++ b/Include/pystate.h @@ -33,7 +33,6 @@ int codecs_initialized; int fscodec_initialized; - #ifdef HAVE_DLOPEN int dlopenflags; #endif @@ -41,6 +40,7 @@ int tscdump; #endif + PyObject *builtins_copy; } PyInterpreterState; #endif diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -16,6 +16,7 @@ import warnings from operator import neg from test.support import TESTFN, unlink, run_unittest, check_warnings +from test.script_helper import assert_python_ok try: import pty, signal except ImportError: @@ -1592,6 +1593,34 @@ data = 'The quick Brown fox Jumped over The lazy Dog'.split() self.assertRaises(TypeError, sorted, data, None, lambda x,y: 0) + +class ShutdownTest(unittest.TestCase): + + def test_cleanup(self): + # Issue #19255: builtins are still available at shutdown + code = """if 1: + import builtins + import sys + + class C: + def __del__(self): + print("before") + # Check that builtins still exist + len(()) + print("after") + + c = C() + # Make this module survive until builtins and sys are cleaned + builtins.here = sys.modules[__name__] + sys.here = sys.modules[__name__] + # Create a reference loop so that this module needs to go + # through a GC phase. + here = sys.modules[__name__] + """ + rc, out, err = assert_python_ok("-c", code) + self.assertEqual(["before", "after"], out.decode().splitlines()) + + def load_tests(loader, tests, pattern): from doctest import DocTestSuite tests.addTest(DocTestSuite(builtins)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #19255: The builtins module is restored to initial value before + cleaning other modules. The sys and builtins modules are cleaned last. + - Issue #20437: Fixed 22 potential bugs when deleting objects references. - Issue #20500: Displaying an exception at interpreter shutdown no longer diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -299,6 +299,14 @@ void _PyModule_Clear(PyObject *m) { + PyObject *d = ((PyModuleObject *)m)->md_dict; + if (d != NULL) + _PyModule_ClearDict(d); +} + +void +_PyModule_ClearDict(PyObject *d) +{ /* To make the execution order of destructors for global objects a bit more predictable, we first zap all objects whose name starts with a single underscore, before we clear @@ -308,11 +316,6 @@ Py_ssize_t pos; PyObject *key, *value; - PyObject *d; - - d = ((PyModuleObject *)m)->md_dict; - if (d == NULL) - return; /* First, clear only names starting with a single underscore */ pos = 0; diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -49,9 +49,13 @@ void _PyImport_Init(void) { + PyInterpreterState *interp = PyThreadState_Get()->interp; initstr = PyUnicode_InternFromString("__init__"); if (initstr == NULL) Py_FatalError("Can't initialize import variables"); + interp->builtins_copy = PyDict_Copy(interp->builtins); + if (interp->builtins_copy == NULL) + Py_FatalError("Can't backup builtins dict"); } void @@ -397,8 +401,10 @@ PyObject *key, *value, *dict; PyInterpreterState *interp = PyThreadState_GET()->interp; PyObject *modules = interp->modules; - PyObject *builtins = interp->builtins; + PyObject *builtins_mod = NULL; + PyObject *sys_mod = NULL; PyObject *weaklist = NULL; + char **p; if (modules == NULL) return; /* Already done */ @@ -411,31 +417,22 @@ /* XXX Perhaps these precautions are obsolete. Who knows? */ - value = PyDict_GetItemString(modules, "builtins"); - if (value != NULL && PyModule_Check(value)) { - dict = PyModule_GetDict(value); + if (Py_VerboseFlag) + PySys_WriteStderr("# clear builtins._\n"); + PyDict_SetItemString(interp->builtins, "_", Py_None); + + for (p = sys_deletes; *p != NULL; p++) { if (Py_VerboseFlag) - PySys_WriteStderr("# clear builtins._\n"); - PyDict_SetItemString(dict, "_", Py_None); + PySys_WriteStderr("# clear sys.%s\n", *p); + PyDict_SetItemString(interp->sysdict, *p, Py_None); } - value = PyDict_GetItemString(modules, "sys"); - if (value != NULL && PyModule_Check(value)) { - char **p; - PyObject *v; - dict = PyModule_GetDict(value); - for (p = sys_deletes; *p != NULL; p++) { - if (Py_VerboseFlag) - PySys_WriteStderr("# clear sys.%s\n", *p); - PyDict_SetItemString(dict, *p, Py_None); - } - for (p = sys_files; *p != NULL; p+=2) { - if (Py_VerboseFlag) - PySys_WriteStderr("# restore sys.%s\n", *p); - v = PyDict_GetItemString(dict, *(p+1)); - if (v == NULL) - v = Py_None; - PyDict_SetItemString(dict, *p, v); - } + for (p = sys_files; *p != NULL; p+=2) { + if (Py_VerboseFlag) + PySys_WriteStderr("# restore sys.%s\n", *p); + value = PyDict_GetItemString(interp->sysdict, *(p+1)); + if (value == NULL) + value = Py_None; + PyDict_SetItemString(interp->sysdict, *p, value); } /* We prepare a list which will receive (name, weakref) tuples of @@ -473,11 +470,15 @@ /* Clear the modules dict. */ PyDict_Clear(modules); - /* Replace the interpreter's reference to builtins with an empty dict - (module globals still have a reference to the original builtins). */ - builtins = interp->builtins; - interp->builtins = PyDict_New(); - Py_DECREF(builtins); + /* Restore the original builtins dict, to ensure that any + user data gets cleared. */ + dict = PyDict_Copy(interp->builtins); + if (dict == NULL) + PyErr_Clear(); + PyDict_Clear(interp->builtins); + if (PyDict_Update(interp->builtins, interp->builtins_copy)) + PyErr_Clear(); + Py_XDECREF(dict); /* Clear module dict copies stored in the interpreter state */ _PyState_ClearModules(); /* Collect references */ @@ -488,7 +489,15 @@ /* Now, if there are any modules left alive, clear their globals to minimize potential leaks. All C extension modules actually end - up here, since they are kept alive in the interpreter state. */ + up here, since they are kept alive in the interpreter state. + + The special treatment of "builtins" here is because even + when it's not referenced as a module, its dictionary is + referenced by almost every module's __builtins__. Since + deleting a module clears its dictionary (even if there are + references left to it), we need to delete the "builtins" + module last. Likewise, we don't delete sys until the very + end because it is implicitly referenced (e.g. by print). */ if (weaklist != NULL) { Py_ssize_t i, n; n = PyList_GET_SIZE(weaklist); @@ -498,17 +507,27 @@ PyObject *mod = PyWeakref_GET_OBJECT(PyTuple_GET_ITEM(tup, 1)); if (mod == Py_None) continue; + assert(PyModule_Check(mod)); + dict = PyModule_GetDict(mod); + if (dict == interp->builtins || dict == interp->sysdict) + continue; Py_INCREF(mod); - assert(PyModule_Check(mod)); if (Py_VerboseFlag && PyUnicode_Check(name)) - PySys_FormatStderr("# cleanup[3] wiping %U\n", - name, mod); + PySys_FormatStderr("# cleanup[3] wiping %U\n", name); _PyModule_Clear(mod); Py_DECREF(mod); } Py_DECREF(weaklist); } + /* Next, delete sys and builtins (in that order) */ + if (Py_VerboseFlag) + PySys_FormatStderr("# cleanup[3] wiping sys\n"); + _PyModule_ClearDict(interp->sysdict); + if (Py_VerboseFlag) + PySys_FormatStderr("# cleanup[3] wiping builtins\n"); + _PyModule_ClearDict(interp->builtins); + /* Clear and delete the modules directory. Actual modules will still be there only if imported during the execution of some destructor. */ diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -72,6 +72,7 @@ interp->modules_by_index = NULL; interp->sysdict = NULL; interp->builtins = NULL; + interp->builtins_copy = NULL; interp->tstate_head = NULL; interp->codec_search_path = NULL; interp->codec_search_cache = NULL; @@ -115,6 +116,7 @@ Py_CLEAR(interp->modules_by_index); Py_CLEAR(interp->sysdict); Py_CLEAR(interp->builtins); + Py_CLEAR(interp->builtins_copy); Py_CLEAR(interp->importlib); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 18:09:43 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 10 Feb 2014 18:09:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Temporary_silence_test_bro?= =?utf-8?q?ken_by_issue19255=2E?= Message-ID: <3fNDBH0sLkz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/fa160c8145e5 changeset: 89098:fa160c8145e5 user: Serhiy Storchaka date: Mon Feb 10 19:09:19 2014 +0200 summary: Temporary silence test broken by issue19255. Remove unused variables. files: Lib/test/test_io.py | 3 ++- Python/import.c | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -2691,7 +2691,8 @@ class PyTextIOWrapperTest(TextIOWrapperTest): io = pyio - shutdown_error = "LookupError: unknown encoding: ascii" + #shutdown_error = "LookupError: unknown encoding: ascii" + shutdown_error = "TypeError: 'NoneType' object is not iterable" class IncrementalNewlineDecoderTest(unittest.TestCase): diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -401,8 +401,6 @@ PyObject *key, *value, *dict; PyInterpreterState *interp = PyThreadState_GET()->interp; PyObject *modules = interp->modules; - PyObject *builtins_mod = NULL; - PyObject *sys_mod = NULL; PyObject *weaklist = NULL; char **p; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 18:27:53 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 10 Feb 2014 18:27:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogaXNzdWUxMjA4NTog?= =?utf-8?q?Use_more_Pythonic_way_to_check_=5Fchild=5Fcreated=2E?= Message-ID: <3fNDbF4d2zz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/734da14489c1 changeset: 89099:734da14489c1 branch: 2.7 parent: 89084:6b10943a5916 user: Serhiy Storchaka date: Mon Feb 10 19:19:53 2014 +0200 summary: issue12085: Use more Pythonic way to check _child_created. _active shouldn't be cached, it set to None on shutdown. files: Lib/subprocess.py | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -645,6 +645,8 @@ class Popen(object): + _child_created = False # Set here since __del__ checks it + def __init__(self, args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, @@ -653,7 +655,6 @@ """Create new Popen instance.""" _cleanup() - self._child_created = False if not isinstance(bufsize, (int, long)): raise TypeError("bufsize must be an integer") @@ -750,11 +751,11 @@ return data - def __del__(self, _maxint=sys.maxint, _active=_active): + def __del__(self, _maxint=sys.maxint): # If __init__ hasn't had a chance to execute (e.g. if it # was passed an undeclared keyword argument), we don't # have a _child_created attribute at all. - if not getattr(self, '_child_created', False): + if not self._child_created: # We didn't get to successfully create a child process. return # In case the child hasn't been waited on, check if it's done. @@ -1330,7 +1331,7 @@ _WTERMSIG=os.WTERMSIG, _WIFEXITED=os.WIFEXITED, _WEXITSTATUS=os.WEXITSTATUS): # This method is called (indirectly) by __del__, so it cannot - # refer to anything outside of its local scope.""" + # refer to anything outside of its local scope. if _WIFSIGNALED(sts): self.returncode = -_WTERMSIG(sts) elif _WIFEXITED(sts): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 18:27:54 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 10 Feb 2014 18:27:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogaXNzdWUxMjA4NTog?= =?utf-8?q?Use_more_Pythonic_way_to_check_=5Fchild=5Fcreated=2E?= Message-ID: <3fNDbG6gG4z7LjZ@mail.python.org> http://hg.python.org/cpython/rev/79a6300f6421 changeset: 89100:79a6300f6421 branch: 3.3 parent: 89085:6adac0d9b933 user: Serhiy Storchaka date: Mon Feb 10 19:20:22 2014 +0200 summary: issue12085: Use more Pythonic way to check _child_created. _active shouldn't be cached, it set to None on shutdown. files: Lib/subprocess.py | 13 ++++++------- 1 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -707,6 +707,9 @@ class Popen(object): + + _child_created = False # Set here since __del__ checks it + def __init__(self, args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS, @@ -717,7 +720,6 @@ """Create new Popen instance.""" _cleanup() - self._child_created = False self._input = None self._communication_started = False if bufsize is None: @@ -859,11 +861,8 @@ # Wait for the process to terminate, to avoid zombies. self.wait() - def __del__(self, _maxsize=sys.maxsize, _active=_active): - # If __init__ hasn't had a chance to execute (e.g. if it - # was passed an undeclared keyword argument), we don't - # have a _child_created attribute at all. - if not getattr(self, '_child_created', False): + def __del__(self, _maxsize=sys.maxsize): + if not self._child_created: # We didn't get to successfully create a child process. return # In case the child hasn't been waited on, check if it's done. @@ -1446,7 +1445,7 @@ _WTERMSIG=os.WTERMSIG, _WIFEXITED=os.WIFEXITED, _WEXITSTATUS=os.WEXITSTATUS): # This method is called (indirectly) by __del__, so it cannot - # refer to anything outside of its local scope.""" + # refer to anything outside of its local scope. if _WIFSIGNALED(sts): self.returncode = -_WTERMSIG(sts) elif _WIFEXITED(sts): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 18:27:56 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 10 Feb 2014 18:27:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_issue12085=3A_Use_more_Pythonic_way_to_check_=5Fchild=5F?= =?utf-8?q?created=2E?= Message-ID: <3fNDbJ1SBVz7LjY@mail.python.org> http://hg.python.org/cpython/rev/a7a62a88380a changeset: 89101:a7a62a88380a parent: 89098:fa160c8145e5 parent: 89100:79a6300f6421 user: Serhiy Storchaka date: Mon Feb 10 19:21:25 2014 +0200 summary: issue12085: Use more Pythonic way to check _child_created. _active shouldn't be cached, it set to None on shutdown. files: Lib/subprocess.py | 13 ++++++------- 1 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -738,6 +738,9 @@ class Popen(object): + + _child_created = False # Set here since __del__ checks it + def __init__(self, args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS, @@ -748,7 +751,6 @@ """Create new Popen instance.""" _cleanup() - self._child_created = False self._input = None self._communication_started = False if bufsize is None: @@ -890,11 +892,8 @@ # Wait for the process to terminate, to avoid zombies. self.wait() - def __del__(self, _maxsize=sys.maxsize, _active=_active): - # If __init__ hasn't had a chance to execute (e.g. if it - # was passed an undeclared keyword argument), we don't - # have a _child_created attribute at all. - if not getattr(self, '_child_created', False): + def __del__(self, _maxsize=sys.maxsize): + if not self._child_created: # We didn't get to successfully create a child process. return # In case the child hasn't been waited on, check if it's done. @@ -1446,7 +1445,7 @@ _WTERMSIG=os.WTERMSIG, _WIFEXITED=os.WIFEXITED, _WEXITSTATUS=os.WEXITSTATUS): # This method is called (indirectly) by __del__, so it cannot - # refer to anything outside of its local scope.""" + # refer to anything outside of its local scope. if _WIFSIGNALED(sts): self.returncode = -_WTERMSIG(sts) elif _WIFEXITED(sts): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 18:27:57 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 10 Feb 2014 18:27:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_Merge_heads?= Message-ID: <3fNDbK2v1xz7LjW@mail.python.org> http://hg.python.org/cpython/rev/3a7638baf511 changeset: 89102:3a7638baf511 branch: 2.7 parent: 89099:734da14489c1 parent: 89094:2ac7551986ba user: Serhiy Storchaka date: Mon Feb 10 19:27:06 2014 +0200 summary: Merge heads files: Doc/library/urllib.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/urllib.rst b/Doc/library/urllib.rst --- a/Doc/library/urllib.rst +++ b/Doc/library/urllib.rst @@ -9,8 +9,9 @@ Python 3 to :mod:`urllib.request`, :mod:`urllib.parse`, and :mod:`urllib.error`. The :term:`2to3` tool will automatically adapt imports when converting your sources to Python 3. - Also note that the :func:`urllib.urlopen` function has been removed in - Python 3 in favor of :func:`urllib2.urlopen`. + Also note that the :func:`urllib.request.urlopen` function in Python 3 is + equivalent to :func:`urllib2.urlopen` and that :func:`urllib.urlopen` has + been removed. .. index:: single: WWW -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 19:18:33 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 10 Feb 2014 19:18:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320505=3A_Use_even?= =?utf-8?q?_shorter_sleep_in_test=5Ftimeout=5Frounding=28=29_to_make_the?= Message-ID: <3fNFjj6QL3z7LjN@mail.python.org> http://hg.python.org/cpython/rev/20dc8d6430eb changeset: 89103:20dc8d6430eb parent: 89101:a7a62a88380a user: Victor Stinner date: Mon Feb 10 19:17:46 2014 +0100 summary: Issue #20505: Use even shorter sleep in test_timeout_rounding() to make the test more reliable (= fail more often on Windows with HPET enabled). files: Lib/test/test_asyncio/test_events.py | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1176,13 +1176,15 @@ 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) self.loop.run_until_complete(wait()) - # The ideal number of call is 6, but on some platforms, the selector + # The ideal number of call is 10, but on some platforms, the selector # may sleep at little bit less than timeout depending on the resolution - # of the clock used by the kernel. Tolerate 2 useless calls on these + # of the clock used by the kernel. Tolerate 5 useless calls on these # platforms. - self.assertLessEqual(self.loop._run_once_counter, 8, + self.assertLessEqual(self.loop._run_once_counter, 15, {'time_info': time.get_clock_info('time'), 'monotonic_info': time.get_clock_info('monotonic'), 'selector': self.loop._selector.__class__.__name__}) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:04:41 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:04:41 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE2MDQyOiBDVkUt?= =?utf-8?q?2013-1752=3A_smtplib_fix_for_unlimited_readline=28=29_from_sock?= =?utf-8?q?et?= Message-ID: <3fNKPP4vhVz7Ljh@mail.python.org> http://hg.python.org/cpython/rev/d62a67318023 changeset: 89104:d62a67318023 branch: 3.3 parent: 88681:3551f184b282 user: Georg Brandl date: Sat Jan 25 09:02:18 2014 +0100 summary: #16042: CVE-2013-1752: smtplib fix for unlimited readline() from socket files: Lib/smtplib.py | 5 +++- Lib/test/mock_socket.py | 9 ++++++- Lib/test/test_smtplib.py | 30 +++++++++++++++++++++++++++- Misc/NEWS | 3 ++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -62,6 +62,7 @@ SMTP_SSL_PORT = 465 CRLF = "\r\n" bCRLF = b"\r\n" +_MAXLINE = 8192 # more than 8 times larger than RFC 821, 4.5.3 OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) @@ -364,7 +365,7 @@ self.file = self.sock.makefile('rb') while 1: try: - line = self.file.readline() + line = self.file.readline(_MAXLINE + 1) except socket.error as e: self.close() raise SMTPServerDisconnected("Connection unexpectedly closed: " @@ -374,6 +375,8 @@ raise SMTPServerDisconnected("Connection unexpectedly closed") if self.debuglevel > 0: print('reply:', repr(line), file=stderr) + if len(line) > _MAXLINE: + raise SMTPResponseException(500, "Line too long.") resp.append(line[4:].strip(b' \t\r\n')) code = line[:3] # Check that the error code is syntactically correct. diff --git a/Lib/test/mock_socket.py b/Lib/test/mock_socket.py --- a/Lib/test/mock_socket.py +++ b/Lib/test/mock_socket.py @@ -21,8 +21,13 @@ """ def __init__(self, lines): self.lines = lines - def readline(self): - return self.lines.pop(0) + b'\r\n' + def readline(self, limit=-1): + result = self.lines.pop(0) + b'\r\n' + if limit >= 0: + # Re-insert the line, removing the \r\n we added. + self.lines.insert(0, result[limit:-2]) + result = result[:limit] + return result def close(self): pass diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -569,6 +569,33 @@ HOST, self.port, 'localhost', 3) + at unittest.skipUnless(threading, 'Threading required for this test.') +class TooLongLineTests(unittest.TestCase): + respdata = b'250 OK' + (b'.' * smtplib._MAXLINE * 2) + b'\n' + + def setUp(self): + self.old_stdout = sys.stdout + self.output = io.StringIO() + sys.stdout = self.output + + self.evt = threading.Event() + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.settimeout(15) + self.port = support.bind_port(self.sock) + servargs = (self.evt, self.respdata, self.sock) + threading.Thread(target=server, args=servargs).start() + self.evt.wait() + self.evt.clear() + + def tearDown(self): + self.evt.wait() + sys.stdout = self.old_stdout + + def testLineTooLong(self): + self.assertRaises(smtplib.SMTPResponseException, smtplib.SMTP, + HOST, self.port, 'localhost', 3) + + sim_users = {'Mr.A at somewhere.com':'John A', 'Ms.B at xn--fo-fka.com':'Sally B', 'Mrs.C at somewhereesle.com':'Ruth C', @@ -885,7 +912,8 @@ def test_main(verbose=None): support.run_unittest(GeneralTests, DebuggingServerTests, NonConnectingTests, - BadHELOServerTests, SMTPSimTests) + BadHELOServerTests, SMTPSimTests, + TooLongLineTests) if __name__ == '__main__': test_main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,9 @@ Library ------- +- Issue #16042: CVE-2013-1752: smtplib: Limit amount of data read by + limiting the call to readline(). Original patch by Christian Heimes. + - Issue #20317: ExitStack.__exit__ could create a self-referential loop if an exception raised by a cleanup operation already had its context set correctly (for example, by the @contextmanager decorator). The infinite -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:04:43 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:04:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzIwMzExOiByZXZl?= =?utf-8?q?rt_changes_to_3=2E3_branch_for_now_until_experts_have_decided_h?= =?utf-8?q?ow_to?= Message-ID: <3fNKPR0n18z7Ljb@mail.python.org> http://hg.python.org/cpython/rev/d393df09e139 changeset: 89105:d393df09e139 branch: 3.3 user: Georg Brandl date: Sat Jan 25 09:11:13 2014 +0100 summary: #20311: revert changes to 3.3 branch for now until experts have decided how to resolve the issue. files: Lib/test/test_epoll.py | 11 ----------- Misc/NEWS | 4 ---- Modules/selectmodule.c | 4 +--- 3 files changed, 1 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_epoll.py b/Lib/test/test_epoll.py --- a/Lib/test/test_epoll.py +++ b/Lib/test/test_epoll.py @@ -217,17 +217,6 @@ server.close() ep.unregister(fd) - def test_timeout_rounding(self): - # epoll_wait() has a resolution of 1 millisecond, check if the timeout - # is correctly rounded to the upper bound - epoll = select.epoll() - self.addCleanup(epoll.close) - for timeout in (1e-2, 1e-3, 1e-4): - t0 = time.monotonic() - epoll.poll(timeout) - dt = time.monotonic() - t0 - self.assertGreaterEqual(dt, timeout) - def test_main(): support.run_unittest(TestEPoll) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,10 +61,6 @@ - Issue #20374: Fix build with GNU readline >= 6.3. -- Issue #20311: select.epoll.poll() now rounds the timeout away from zero, - instead of rounding towards zero. For example, a timeout of one microsecond - is now rounded to one millisecond, instead of being rounded to zero. - - Issue #20262: Warnings are raised now when duplicate names are added in the ZIP file or too long ZIP file comment is truncated. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -1379,9 +1379,7 @@ return NULL; } else { - /* epoll_wait() has a resolution of 1 millisecond, round away from zero - to wait *at least* dtimeout seconds. */ - timeout = (int)ceil(dtimeout * 1000.0); + timeout = (int)(dtimeout * 1000.0); } if (maxevents == -1) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:04:47 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:04:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogZG9jOiBweWRvYyB0?= =?utf-8?q?opic_and_suspicious_markup_update?= Message-ID: <3fNKPW6wD4z7Lk4@mail.python.org> http://hg.python.org/cpython/rev/9a9dea57ed94 changeset: 89106:9a9dea57ed94 branch: 3.3 user: Georg Brandl date: Sat Jan 25 09:15:44 2014 +0100 summary: doc: pydoc topic and suspicious markup update files: Doc/tools/sphinxext/susp-ignored.csv | 1 + Lib/pydoc_data/topics.py | 148 +++++++------- 2 files changed, 75 insertions(+), 74 deletions(-) diff --git a/Doc/tools/sphinxext/susp-ignored.csv b/Doc/tools/sphinxext/susp-ignored.csv --- a/Doc/tools/sphinxext/susp-ignored.csv +++ b/Doc/tools/sphinxext/susp-ignored.csv @@ -287,3 +287,4 @@ whatsnew/changelog,,::,": Fix FTP tests for IPv6, bind to ""::1"" instead of ""localhost""." whatsnew/changelog,,::,": Use ""127.0.0.1"" or ""::1"" instead of ""localhost"" as much as" whatsnew/changelog,,:password,user:password +whatsnew/changelog,,:gz,w:gz diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,79 +1,79 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sun Oct 27 09:07:55 2013 -topics = {'assert': '\nThe ``assert`` statement\n************************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, ``assert expression``, is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, ``assert expression1, expression2``, is equivalent\nto\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that ``__debug__`` and ``AssertionError``\nrefer to the built-in variables with those names. In the current\nimplementation, the built-in variable ``__debug__`` is ``True`` under\nnormal circumstances, ``False`` when optimization is requested\n(command line option -O). The current code generator emits no code\nfor an assert statement when optimization is requested at compile\ntime. Note that it is unnecessary to include the source code for the\nexpression that failed in the error message; it will be displayed as\npart of the stack trace.\n\nAssignments to ``__debug__`` are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', - 'assignment': '\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The object\n must be an iterable with the same number of items as there are\n targets in the target list, and the items are assigned, from left to\n right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an asterisk,\n called a "starred" target: The object must be a sequence with at\n least as many items as there are targets in the target list, minus\n one. The first items of the sequence are assigned, from left to\n right, to the targets before the starred target. The final items\n of the sequence are assigned to the targets after the starred\n target. A list of the remaining items in the sequence is then\n assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of items\n as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a ``global`` or ``nonlocal``\n statement in the current code block: the name is bound to the\n object in the current local namespace.\n\n * Otherwise: the name is bound to the object in the global namespace\n or the outer namespace determined by ``nonlocal``, respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in square\n brackets: The object must be an iterable with the same number of\n items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, ``TypeError`` is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily ``AttributeError``).\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n ``a.x`` can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target ``a.x`` is\n always set as an instance attribute, creating it if necessary.\n Thus, the two occurrences of ``a.x`` do not necessarily refer to the\n same attribute: if the RHS expression refers to a class attribute,\n the LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with ``property()``.\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, ``IndexError`` is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the ``__setitem__()`` method is called\n with appropriate arguments.\n\n* If the target is a slicing: The primary expression in the reference\n is evaluated. It should yield a mutable sequence object (such as a\n list). The assigned object should be a sequence object of the same\n type. Next, the lower and upper bound expressions are evaluated,\n insofar they are present; defaults are zero and the sequence\'s\n length. The bounds should evaluate to integers. If either bound is\n negative, the sequence\'s length is added to it. The resulting\n bounds are clipped to lie between zero and the sequence\'s length,\n inclusive. Finally, the sequence object is asked to replace the\n slice with the items of the assigned sequence. The length of the\n slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample ``a, b = b, a`` swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints ``[0, 2]``:\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print(x)\n\nSee also:\n\n **PEP 3132** - Extended Iterable Unpacking\n The specification for the ``*target`` feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like ``x += 1`` can be rewritten as\n``x = x + 1`` to achieve a similar, but not exactly equal effect. In\nthe augmented version, ``x`` is only evaluated once. Also, when\npossible, the actual operation is performed *in-place*, meaning that\nrather than creating a new object and assigning that to the target,\nthe old object is modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', - 'atom-identifiers': '\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a ``NameError`` exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier\n``__spam`` occurring in a class named ``Ham`` will be transformed to\n``_Ham__spam``. This transformation is independent of the syntactical\ncontext in which the identifier is used. If the transformed name is\nextremely long (longer than 255 characters), implementation defined\ntruncation may happen. If the class name consists only of underscores,\nno transformation is done.\n', +# Autogenerated by Sphinx on Sat Jan 25 09:13:25 2014 +topics = {'assert': '\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', + 'assignment': '\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints "[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', + 'atom-identifiers': '\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', 'atom-literals': "\nLiterals\n********\n\nPython supports string and bytes literals and various numeric\nliterals:\n\n literal ::= stringliteral | bytesliteral\n | integer | floatnumber | imagnumber\n\nEvaluation of a literal yields an object of the given type (string,\nbytes, integer, floating point number, complex number) with the given\nvalue. The value may be approximated in the case of floating point\nand imaginary (complex) literals. See section *Literals* for details.\n\nAll literals correspond to immutable data types, and hence the\nobject's identity is less important than its value. Multiple\nevaluations of literals with the same value (either the same\noccurrence in the program text or a different occurrence) may obtain\nthe same object or a different object with the same value.\n", - 'attribute-access': '\nCustomizing attribute access\n****************************\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of ``x.name``)\nfor class instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for ``self``). ``name`` is the attribute name.\n This method should return the (computed) attribute value or raise\n an ``AttributeError`` exception.\n\n Note that if the attribute is found through the normal mechanism,\n ``__getattr__()`` is not called. (This is an intentional asymmetry\n between ``__getattr__()`` and ``__setattr__()``.) This is done both\n for efficiency reasons and because otherwise ``__getattr__()``\n would have no way to access other attributes of the instance. Note\n that at least for instance variables, you can fake total control by\n not inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n ``__getattribute__()`` method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines\n ``__getattr__()``, the latter will not be called unless\n ``__getattribute__()`` either calls it explicitly or raises an\n ``AttributeError``. This method should return the (computed)\n attribute value or raise an ``AttributeError`` exception. In order\n to avoid infinite recursion in this method, its implementation\n should always call the base class method with the same name to\n access any attributes it needs, for example,\n ``object.__getattribute__(self, name)``.\n\n Note: This method may still be bypassed when looking up special methods\n as the result of implicit invocation via language syntax or\n built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If ``__setattr__()`` wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n ``object.__setattr__(self, name, value)``.\n\nobject.__delattr__(self, name)\n\n Like ``__setattr__()`` but for attribute deletion instead of\n assignment. This should only be implemented if ``del obj.name`` is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when ``dir()`` is called on the object. A sequence must be\n returned. ``dir()`` converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n========================\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' ``__dict__``.\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or ``None`` when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an\n ``AttributeError`` exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n====================\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: ``__get__()``, ``__set__()``, and\n``__delete__()``. If any of those methods are defined for an object,\nit is said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, ``a.x`` has a\nlookup chain starting with ``a.__dict__[\'x\']``, then\n``type(a).__dict__[\'x\']``, and continuing through the base classes of\n``type(a)`` excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, ``a.x``.\nHow the arguments are assembled depends on ``a``:\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: ``x.__get__(a)``.\n\nInstance Binding\n If binding to an object instance, ``a.x`` is transformed into the\n call: ``type(a).__dict__[\'x\'].__get__(a, type(a))``.\n\nClass Binding\n If binding to a class, ``A.x`` is transformed into the call:\n ``A.__dict__[\'x\'].__get__(None, A)``.\n\nSuper Binding\n If ``a`` is an instance of ``super``, then the binding ``super(B,\n obj).m()`` searches ``obj.__class__.__mro__`` for the base class\n ``A`` immediately preceding ``B`` and then invokes the descriptor\n with the call: ``A.__dict__[\'m\'].__get__(obj, obj.__class__)``.\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of ``__get__()``, ``__set__()`` and ``__delete__()``.\nIf it does not define ``__get__()``, then accessing the attribute will\nreturn the descriptor object itself unless there is a value in the\nobject\'s instance dictionary. If the descriptor defines ``__set__()``\nand/or ``__delete__()``, it is a data descriptor; if it defines\nneither, it is a non-data descriptor. Normally, data descriptors\ndefine both ``__get__()`` and ``__set__()``, while non-data\ndescriptors have just the ``__get__()`` method. Data descriptors with\n``__set__()`` and ``__get__()`` defined always override a redefinition\nin an instance dictionary. In contrast, non-data descriptors can be\noverridden by instances.\n\nPython methods (including ``staticmethod()`` and ``classmethod()``)\nare implemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe ``property()`` function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n=========\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n class, *__slots__* reserves space for the declared variables and\n prevents the automatic creation of *__dict__* and *__weakref__* for\n each instance.\n\n\nNotes on using *__slots__*\n--------------------------\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises ``AttributeError``. If\n dynamic assignment of new variables is desired, then add\n ``\'__dict__\'`` to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes defining\n *__slots__* do not support weak references to its instances. If weak\n reference support is needed, then add ``\'__weakref__\'`` to the\n sequence of strings in the *__slots__* declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the instance\n variable defined by the base class slot is inaccessible (except by\n retrieving its descriptor directly from the base class). This\n renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as ``int``, ``str`` and\n ``tuple``.\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings may\n also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n', - 'attribute-references': '\nAttribute references\n********************\n\nAn attribute reference is a primary followed by a period and a name:\n\n attributeref ::= primary "." identifier\n\nThe primary must evaluate to an object of a type that supports\nattribute references, which most objects do. This object is then\nasked to produce the attribute whose name is the identifier (which can\nbe customized by overriding the ``__getattr__()`` method). If this\nattribute is not available, the exception ``AttributeError`` is\nraised. Otherwise, the type and value of the object produced is\ndetermined by the object. Multiple evaluations of the same attribute\nreference may yield different objects.\n', - 'augassign': '\nAugmented assignment statements\n*******************************\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like ``x += 1`` can be rewritten as\n``x = x + 1`` to achieve a similar, but not exactly equal effect. In\nthe augmented version, ``x`` is only evaluated once. Also, when\npossible, the actual operation is performed *in-place*, meaning that\nrather than creating a new object and assigning that to the target,\nthe old object is modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', - 'binary': '\nBinary arithmetic operations\n****************************\n\nThe binary arithmetic operations have the conventional priority\nlevels. Note that some of these operations also apply to certain non-\nnumeric types. Apart from the power operator, there are only two\nlevels, one for multiplicative operators and one for additive\noperators:\n\n m_expr ::= u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr\n | m_expr "%" u_expr\n a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr\n\nThe ``*`` (multiplication) operator yields the product of its\narguments. The arguments must either both be numbers, or one argument\nmust be an integer and the other must be a sequence. In the former\ncase, the numbers are converted to a common type and then multiplied\ntogether. In the latter case, sequence repetition is performed; a\nnegative repetition factor yields an empty sequence.\n\nThe ``/`` (division) and ``//`` (floor division) operators yield the\nquotient of their arguments. The numeric arguments are first\nconverted to a common type. Division of integers yields a float, while\nfloor division of integers results in an integer; the result is that\nof mathematical division with the \'floor\' function applied to the\nresult. Division by zero raises the ``ZeroDivisionError`` exception.\n\nThe ``%`` (modulo) operator yields the remainder from the division of\nthe first argument by the second. The numeric arguments are first\nconverted to a common type. A zero right argument raises the\n``ZeroDivisionError`` exception. The arguments may be floating point\nnumbers, e.g., ``3.14%0.7`` equals ``0.34`` (since ``3.14`` equals\n``4*0.7 + 0.34``.) The modulo operator always yields a result with\nthe same sign as its second operand (or zero); the absolute value of\nthe result is strictly smaller than the absolute value of the second\noperand [1].\n\nThe floor division and modulo operators are connected by the following\nidentity: ``x == (x//y)*y + (x%y)``. Floor division and modulo are\nalso connected with the built-in function ``divmod()``: ``divmod(x, y)\n== (x//y, x%y)``. [2].\n\nIn addition to performing the modulo operation on numbers, the ``%``\noperator is also overloaded by string objects to perform old-style\nstring formatting (also known as interpolation). The syntax for\nstring formatting is described in the Python Library Reference,\nsection *printf-style String Formatting*.\n\nThe floor division operator, the modulo operator, and the ``divmod()``\nfunction are not defined for complex numbers. Instead, convert to a\nfloating point number using the ``abs()`` function if appropriate.\n\nThe ``+`` (addition) operator yields the sum of its arguments. The\narguments must either both be numbers or both sequences of the same\ntype. In the former case, the numbers are converted to a common type\nand then added together. In the latter case, the sequences are\nconcatenated.\n\nThe ``-`` (subtraction) operator yields the difference of its\narguments. The numeric arguments are first converted to a common\ntype.\n', - 'bitwise': '\nBinary bitwise operations\n*************************\n\nEach of the three bitwise operations has a different priority level:\n\n and_expr ::= shift_expr | and_expr "&" shift_expr\n xor_expr ::= and_expr | xor_expr "^" and_expr\n or_expr ::= xor_expr | or_expr "|" xor_expr\n\nThe ``&`` operator yields the bitwise AND of its arguments, which must\nbe integers.\n\nThe ``^`` operator yields the bitwise XOR (exclusive OR) of its\narguments, which must be integers.\n\nThe ``|`` operator yields the bitwise (inclusive) OR of its arguments,\nwhich must be integers.\n', - 'bltin-code-objects': '\nCode Objects\n************\n\nCode objects are used by the implementation to represent "pseudo-\ncompiled" executable Python code such as a function body. They differ\nfrom function objects because they don\'t contain a reference to their\nglobal execution environment. Code objects are returned by the built-\nin ``compile()`` function and can be extracted from function objects\nthrough their ``__code__`` attribute. See also the ``code`` module.\n\nA code object can be executed or evaluated by passing it (instead of a\nsource string) to the ``exec()`` or ``eval()`` built-in functions.\n\nSee *The standard type hierarchy* for more information.\n', - 'bltin-ellipsis-object': '\nThe Ellipsis Object\n*******************\n\nThis object is commonly used by slicing (see *Slicings*). It supports\nno special operations. There is exactly one ellipsis object, named\n``Ellipsis`` (a built-in name). ``type(Ellipsis)()`` produces the\n``Ellipsis`` singleton.\n\nIt is written as ``Ellipsis`` or ``...``.\n', - 'bltin-null-object': "\nThe Null Object\n***************\n\nThis object is returned by functions that don't explicitly return a\nvalue. It supports no special operations. There is exactly one null\nobject, named ``None`` (a built-in name). ``type(None)()`` produces\nthe same singleton.\n\nIt is written as ``None``.\n", - 'bltin-type-objects': "\nType Objects\n************\n\nType objects represent the various object types. An object's type is\naccessed by the built-in function ``type()``. There are no special\noperations on types. The standard module ``types`` defines names for\nall standard built-in types.\n\nTypes are written like this: ````.\n", - 'booleans': '\nBoolean operations\n******************\n\n or_test ::= and_test | or_test "or" and_test\n and_test ::= not_test | and_test "and" not_test\n not_test ::= comparison | "not" not_test\n\nIn the context of Boolean operations, and also when expressions are\nused by control flow statements, the following values are interpreted\nas false: ``False``, ``None``, numeric zero of all types, and empty\nstrings and containers (including strings, tuples, lists,\ndictionaries, sets and frozensets). All other values are interpreted\nas true. User-defined objects can customize their truth value by\nproviding a ``__bool__()`` method.\n\nThe operator ``not`` yields ``True`` if its argument is false,\n``False`` otherwise.\n\nThe expression ``x and y`` first evaluates *x*; if *x* is false, its\nvalue is returned; otherwise, *y* is evaluated and the resulting value\nis returned.\n\nThe expression ``x or y`` first evaluates *x*; if *x* is true, its\nvalue is returned; otherwise, *y* is evaluated and the resulting value\nis returned.\n\n(Note that neither ``and`` nor ``or`` restrict the value and type they\nreturn to ``False`` and ``True``, but rather return the last evaluated\nargument. This is sometimes useful, e.g., if ``s`` is a string that\nshould be replaced by a default value if it is empty, the expression\n``s or \'foo\'`` yields the desired value. Because ``not`` has to\ninvent a value anyway, it does not bother to return a value of the\nsame type as its argument, so e.g., ``not \'foo\'`` yields ``False``,\nnot ``\'\'``.)\n', - 'break': '\nThe ``break`` statement\n***********************\n\n break_stmt ::= "break"\n\n``break`` may only occur syntactically nested in a ``for`` or\n``while`` loop, but not nested in a function or class definition\nwithin that loop.\n\nIt terminates the nearest enclosing loop, skipping the optional\n``else`` clause if the loop has one.\n\nIf a ``for`` loop is terminated by ``break``, the loop control target\nkeeps its current value.\n\nWhen ``break`` passes control out of a ``try`` statement with a\n``finally`` clause, that ``finally`` clause is executed before really\nleaving the loop.\n', - 'callable-types': '\nEmulating callable objects\n**************************\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, ``x(arg1, arg2, ...)`` is a shorthand for\n ``x.__call__(arg1, arg2, ...)``.\n', - 'calls': '\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","] | comprehension] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," keyword_arguments] ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nA trailing comma may be present after the positional and keyword\narguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and all objects having a\n``__call__()`` method are callable). All argument expressions are\nevaluated before the call is attempted. Please refer to section\n*Function definitions* for the syntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a ``TypeError`` exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is ``None``, it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a\n``TypeError`` exception is raised. Otherwise, the list of filled\nslots is used as the argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use ``PyArg_ParseTuple()`` to\nparse their arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a ``TypeError`` exception is raised, unless a formal parameter\nusing the syntax ``*identifier`` is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a ``TypeError`` exception is raised, unless a formal parameter\nusing the syntax ``**identifier`` is present; in this case, that\nformal parameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax ``*expression`` appears in the function call,\n``expression`` must evaluate to an iterable. Elements from this\niterable are treated as if they were additional positional arguments;\nif there are positional arguments *x1*, ..., *xN*, and ``expression``\nevaluates to a sequence *y1*, ..., *yM*, this is equivalent to a call\nwith M+N positional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the ``*expression`` syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the ``**expression`` argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print(a, b)\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the ``*expression``\nsyntax to be used in the same call, so in practice this confusion does\nnot arise.\n\nIf the syntax ``**expression`` appears in the function call,\n``expression`` must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both ``expression`` and as an explicit keyword argument,\na ``TypeError`` exception is raised.\n\nFormal parameters using the syntax ``*identifier`` or ``**identifier``\ncannot be used as positional argument slots or as keyword argument\nnames.\n\nA call always returns some value, possibly ``None``, unless it raises\nan exception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a ``return``\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a ``__call__()`` method; the effect is then\n the same as if that method was called.\n', - 'class': '\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class ``object``; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with ``self.name = value``. Both class and\ninstance attributes are accessible through the notation\n"``self.name``", and an instance attribute hides a class attribute\nwith the same name when accessed in this way. Class attributes can be\nused as defaults for instance attributes, but using mutable values\nthere can lead to unexpected results. *Descriptors* can be used to\ncreate instance variables with different implementation details.\n\nSee also:\n\n **PEP 3115** - Metaclasses in Python 3 **PEP 3129** - Class\n Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless there\n is a ``finally`` clause which happens to raise another exception.\n That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of an\n exception or the execution of a ``return``, ``continue``, or\n ``break`` statement.\n\n[3] A string literal appearing as the first statement in the function\n body is transformed into the function\'s ``__doc__`` attribute and\n therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s ``__doc__`` item and\n therefore the class\'s *docstring*.\n', - 'comparisons': '\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like ``a < b < c`` have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: ``True`` or ``False``.\n\nComparisons can be chained arbitrarily, e.g., ``x < y <= z`` is\nequivalent to ``x < y and y <= z``, except that ``y`` is evaluated\nonly once (but in both cases ``z`` is not evaluated at all when ``x <\ny`` is found to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then ``a op1 b op2 c ... y\nopN z`` is equivalent to ``a op1 b and b op2 c and ... y opN z``,\nexcept that each expression is evaluated at most once.\n\nNote that ``a op1 b op2 c`` doesn\'t imply any kind of comparison\nbetween *a* and *c*, so that, e.g., ``x < y > z`` is perfectly legal\n(though perhaps not pretty).\n\nThe operators ``<``, ``>``, ``==``, ``>=``, ``<=``, and ``!=`` compare\nthe values of two objects. The objects need not have the same type.\nIf both are numbers, they are converted to a common type. Otherwise,\nthe ``==`` and ``!=`` operators *always* consider objects of different\ntypes to be unequal, while the ``<``, ``>``, ``>=`` and ``<=``\noperators raise a ``TypeError`` when comparing objects of different\ntypes that do not implement these operators for the given pair of\ntypes. You can control comparison behavior of objects of non-built-in\ntypes by defining rich comparison methods like ``__gt__()``, described\nin section *Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values ``float(\'NaN\')`` and ``Decimal(\'NaN\')`` are special. The\n are identical to themselves, ``x is x`` but are not equal to\n themselves, ``x != x``. Additionally, comparing any value to a\n not-a-number value will return ``False``. For example, both ``3 <\n float(\'NaN\')`` and ``float(\'NaN\') < 3`` will return ``False``.\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric equivalents\n (the result of the built-in function ``ord()``) of their characters.\n [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison of\n corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, ``[1,2,x] <= [1,2,y]`` has the\n same value as ``x <= y``. If the corresponding element does not\n exist, the shorter sequence is ordered first (for example, ``[1,2] <\n [1,2,3]``).\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same ``(key, value)`` pairs. Order comparisons ``(\'<\', \'<=\', \'>=\',\n \'>\')`` raise ``TypeError``.\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets ``{1,2}`` and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, ``min()``, ``max()``, and ``sorted()`` produce\n undefined results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they are\n the same object; the choice whether one object is considered smaller\n or larger than another one is made arbitrarily but consistently\n within one execution of a program.\n\nComparison of objects of the differing types depends on whether either\nof the types provide explicit support for the comparison. Most\nnumeric types can be compared with one another. When cross-type\ncomparison is not supported, the comparison method returns\n``NotImplemented``.\n\nThe operators ``in`` and ``not in`` test for membership. ``x in s``\nevaluates to true if *x* is a member of *s*, and false otherwise. ``x\nnot in s`` returns the negation of ``x in s``. All built-in sequences\nand set types support this as well as dictionary, for which ``in``\ntests whether a the dictionary has a given key. For container types\nsuch as list, tuple, set, frozenset, dict, or collections.deque, the\nexpression ``x in y`` is equivalent to ``any(x is e or x == e for e in\ny)``.\n\nFor the string and bytes types, ``x in y`` is true if and only if *x*\nis a substring of *y*. An equivalent test is ``y.find(x) != -1``.\nEmpty strings are always considered to be a substring of any other\nstring, so ``"" in "abc"`` will return ``True``.\n\nFor user-defined classes which define the ``__contains__()`` method,\n``x in y`` is true if and only if ``y.__contains__(x)`` is true.\n\nFor user-defined classes which do not define ``__contains__()`` but do\ndefine ``__iter__()``, ``x in y`` is true if some value ``z`` with ``x\n== z`` is produced while iterating over ``y``. If an exception is\nraised during the iteration, it is as if ``in`` raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n``__getitem__()``, ``x in y`` is true if and only if there is a non-\nnegative integer index *i* such that ``x == y[i]``, and all lower\ninteger indices do not raise ``IndexError`` exception. (If any other\nexception is raised, it is as if ``in`` raised that exception).\n\nThe operator ``not in`` is defined to have the inverse true value of\n``in``.\n\nThe operators ``is`` and ``is not`` test for object identity: ``x is\ny`` is true if and only if *x* and *y* are the same object. ``x is\nnot y`` yields the inverse truth value. [4]\n', - 'compound': '\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe ``if``, ``while`` and ``for`` statements implement traditional\ncontrol flow constructs. ``try`` specifies exception handlers and/or\ncleanup code for a group of statements, while the ``with`` statement\nallows the execution of initialization and finalization code around a\nblock of code. Function and class definitions are also syntactically\ncompound statements.\n\nCompound statements consist of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which ``if`` clause a following ``else`` clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n``print()`` calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a ``NEWLINE`` possibly followed by\na ``DEDENT``. Also note that optional continuation clauses always\nbegin with a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling ``else``\' problem is solved in Python by\nrequiring nested ``if`` statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe ``if`` statement\n====================\n\nThe ``if`` statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the ``if`` statement is executed or evaluated).\nIf all expressions are false, the suite of the ``else`` clause, if\npresent, is executed.\n\n\nThe ``while`` statement\n=======================\n\nThe ``while`` statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the ``else`` clause, if present, is\nexecuted and the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ngoes back to testing the expression.\n\n\nThe ``for`` statement\n=====================\n\nThe ``for`` statement is used to iterate over the elements of a\nsequence (such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n``expression_list``. The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a ``StopIteration``\nexception), the suite in the ``else`` clause, if present, is executed,\nand the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ncontinues with the next item, or with the ``else`` clause if there was\nno next item.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function ``range()`` returns an\niterator of integers suitable to emulate the effect of Pascal\'s ``for\ni := a to b do``; e.g., ``list(range(3))`` returns the list ``[0, 1,\n2]``.\n\nNote: There is a subtlety when the sequence is being modified by the loop\n (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe ``try`` statement\n=====================\n\nThe ``try`` statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" target]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe ``except`` clause(s) specify one or more exception handlers. When\nno exception occurs in the ``try`` clause, no exception handler is\nexecuted. When an exception occurs in the ``try`` suite, a search for\nan exception handler is started. This search inspects the except\nclauses in turn until one is found that matches the exception. An\nexpression-less except clause, if present, must be last; it matches\nany exception. For an except clause with an expression, that\nexpression is evaluated, and the clause matches the exception if the\nresulting object is "compatible" with the exception. An object is\ncompatible with an exception if it is the class or a base class of the\nexception object or a tuple containing an item compatible with the\nexception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire ``try`` statement\nraised the exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the ``as`` keyword in that except clause,\nif present, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using ``as target``, it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the ``sys`` module and can be access via\n``sys.exc_info()``. ``sys.exc_info()`` returns a 3-tuple consisting of\nthe exception class, the exception instance and a traceback object\n(see section *The standard type hierarchy*) identifying the point in\nthe program where the exception occurred. ``sys.exc_info()`` values\nare restored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional ``else`` clause is executed if and when control flows off\nthe end of the ``try`` clause. [2] Exceptions in the ``else`` clause\nare not handled by the preceding ``except`` clauses.\n\nIf ``finally`` is present, it specifies a \'cleanup\' handler. The\n``try`` clause is executed, including any ``except`` and ``else``\nclauses. If an exception occurs in any of the clauses and is not\nhandled, the exception is temporarily saved. The ``finally`` clause is\nexecuted. If there is a saved exception it is re-raised at the end of\nthe ``finally`` clause. If the ``finally`` clause raises another\nexception, the saved exception is set as the context of the new\nexception. If the ``finally`` clause executes a ``return`` or\n``break`` statement, the saved exception is discarded:\n\n def f():\n try:\n 1/0\n finally:\n return 42\n\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the ``finally`` clause.\n\nWhen a ``return``, ``break`` or ``continue`` statement is executed in\nthe ``try`` suite of a ``try``...``finally`` statement, the\n``finally`` clause is also executed \'on the way out.\' A ``continue``\nstatement is illegal in the ``finally`` clause. (The reason is a\nproblem with the current implementation --- this restriction may be\nlifted in the future).\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the ``raise`` statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe ``with`` statement\n======================\n\nThe ``with`` statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common\n``try``...``except``...``finally`` usage patterns to be encapsulated\nfor convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the ``with`` statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the ``with_item``)\n is evaluated to obtain a context manager.\n\n2. The context manager\'s ``__exit__()`` is loaded for later use.\n\n3. The context manager\'s ``__enter__()`` method is invoked.\n\n4. If a target was included in the ``with`` statement, the return\n value from ``__enter__()`` is assigned to it.\n\n Note: The ``with`` statement guarantees that if the ``__enter__()``\n method returns without an error, then ``__exit__()`` will always\n be called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s ``__exit__()`` method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to ``__exit__()``. Otherwise,\n three ``None`` arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the ``__exit__()`` method was false, the exception is\n reraised. If the return value was true, the exception is\n suppressed, and execution continues with the statement following\n the ``with`` statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from ``__exit__()`` is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple ``with`` statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* ``=``\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the "``*``" must also have a default value ---\nthis is a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use ``None`` as the\ndefault, and explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n"``*identifier``" is present, it is initialized to a tuple receiving\nany excess positional parameters, defaulting to the empty tuple. If\nthe form "``**identifier``" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after "``*``" or "``*identifier``" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "``: expression``"\nfollowing the parameter name. Any parameter may have an annotation\neven those of the form ``*identifier`` or ``**identifier``. Functions\nmay have "return" annotation of the form "``-> expression``" after the\nparameter list. These annotations can be any valid Python expression\nand are evaluated when the function definition is executed.\nAnnotations may be evaluated in a different order than they appear in\nthe source code. The presence of annotations does not change the\nsemantics of a function. The annotation values are available as\nvalues of a dictionary keyed by the parameters\' names in the\n``__annotations__`` attribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a "``def``" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The "``def``" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A "``def``"\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also:\n\n **PEP 3107** - Function Annotations\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class ``object``; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with ``self.name = value``. Both class and\ninstance attributes are accessible through the notation\n"``self.name``", and an instance attribute hides a class attribute\nwith the same name when accessed in this way. Class attributes can be\nused as defaults for instance attributes, but using mutable values\nthere can lead to unexpected results. *Descriptors* can be used to\ncreate instance variables with different implementation details.\n\nSee also:\n\n **PEP 3115** - Metaclasses in Python 3 **PEP 3129** - Class\n Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless there\n is a ``finally`` clause which happens to raise another exception.\n That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of an\n exception or the execution of a ``return``, ``continue``, or\n ``break`` statement.\n\n[3] A string literal appearing as the first statement in the function\n body is transformed into the function\'s ``__doc__`` attribute and\n therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s ``__doc__`` item and\n therefore the class\'s *docstring*.\n', - 'context-managers': '\nWith Statement Context Managers\n*******************************\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a ``with`` statement. The context\nmanager handles the entry into, and the exit from, the desired runtime\ncontext for the execution of the block of code. Context managers are\nnormally invoked using the ``with`` statement (described in section\n*The with statement*), but can also be used by directly invoking their\nmethods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The ``with``\n statement will bind this method\'s return value to the target(s)\n specified in the ``as`` clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be ``None``.\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that ``__exit__()`` methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` statement.\n', - 'continue': '\nThe ``continue`` statement\n**************************\n\n continue_stmt ::= "continue"\n\n``continue`` may only occur syntactically nested in a ``for`` or\n``while`` loop, but not nested in a function or class definition or\n``finally`` clause within that loop. It continues with the next cycle\nof the nearest enclosing loop.\n\nWhen ``continue`` passes control out of a ``try`` statement with a\n``finally`` clause, that ``finally`` clause is executed before really\nstarting the next loop cycle.\n', - 'conversions': '\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," this means\nthat the operator implementation for built-in types works that way:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the other\n is converted to floating point;\n\n* otherwise, both must be integers and no conversion is necessary.\n\nSome additional rules apply for certain operators (e.g., a string left\nargument to the \'%\' operator). Extensions must define their own\nconversion behavior.\n', - 'customization': '\nBasic customization\n*******************\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. ``__new__()`` is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of ``__new__()`` should be the new object instance (usually\n an instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s ``__new__()`` method using\n ``super(currentclass, cls).__new__(cls[, ...])`` with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If ``__new__()`` returns an instance of *cls*, then the new\n instance\'s ``__init__()`` method will be invoked like\n ``__init__(self[, ...])``, where *self* is the new instance and the\n remaining arguments are the same as were passed to ``__new__()``.\n\n If ``__new__()`` does not return an instance of *cls*, then the new\n instance\'s ``__init__()`` method will not be invoked.\n\n ``__new__()`` is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called when the instance is created. The arguments are those\n passed to the class constructor expression. If a base class has an\n ``__init__()`` method, the derived class\'s ``__init__()`` method,\n if any, must explicitly call it to ensure proper initialization of\n the base class part of the instance; for example:\n ``BaseClass.__init__(self, [args...])``. As a special constraint\n on constructors, no value may be returned; doing so will cause a\n ``TypeError`` to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a ``__del__()`` method,\n the derived class\'s ``__del__()`` method, if any, must explicitly\n call it to ensure proper deletion of the base class part of the\n instance. Note that it is possible (though not recommended!) for\n the ``__del__()`` method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n ``__del__()`` methods are called for objects that still exist when\n the interpreter exits.\n\n Note: ``del x`` doesn\'t directly call ``x.__del__()`` --- the former\n decrements the reference count for ``x`` by one, and the latter\n is only called when ``x``\'s reference count reaches zero. Some\n common situations that may prevent the reference count of an\n object from going to zero include: circular references between\n objects (e.g., a doubly-linked list or a tree data structure with\n parent and child pointers); a reference to the object on the\n stack frame of a function that caught an exception (the traceback\n stored in ``sys.exc_info()[2]`` keeps the stack frame alive); or\n a reference to the object on the stack frame that raised an\n unhandled exception in interactive mode (the traceback stored in\n ``sys.last_traceback`` keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing ``None`` in\n ``sys.last_traceback``. Circular references which are garbage are\n detected when the option cycle detector is enabled (it\'s on by\n default), but can only be cleaned up if there are no Python-\n level ``__del__()`` methods involved. Refer to the documentation\n for the ``gc`` module for more information about how\n ``__del__()`` methods are handled by the cycle detector,\n particularly the description of the ``garbage`` value.\n\n Warning: Due to the precarious circumstances under which ``__del__()``\n methods are invoked, exceptions that occur during their execution\n are ignored, and a warning is printed to ``sys.stderr`` instead.\n Also, when ``__del__()`` is invoked in response to a module being\n deleted (e.g., when execution of the program is done), other\n globals referenced by the ``__del__()`` method may already have\n been deleted or in the process of being torn down (e.g. the\n import machinery shutting down). For this reason, ``__del__()``\n methods should do the absolute minimum needed to maintain\n external invariants. Starting with version 1.5, Python\n guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the ``__del__()`` method is called.\n\nobject.__repr__(self)\n\n Called by the ``repr()`` built-in function to compute the\n "official" string representation of an object. If at all possible,\n this should look like a valid Python expression that could be used\n to recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n ``<...some useful description...>`` should be returned. The return\n value must be a string object. If a class defines ``__repr__()``\n but not ``__str__()``, then ``__repr__()`` is also used when an\n "informal" string representation of instances of that class is\n required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by ``str(object)`` and the built-in functions ``format()``\n and ``print()`` to compute the "informal" or nicely printable\n string representation of an object. The return value must be a\n *string* object.\n\n This method differs from ``object.__repr__()`` in that there is no\n expectation that ``__str__()`` return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type ``object``\n calls ``object.__repr__()``.\n\nobject.__bytes__(self)\n\n Called by ``bytes()`` to compute a byte-string representation of an\n object. This should return a ``bytes`` object.\n\nobject.__format__(self, format_spec)\n\n Called by the ``format()`` built-in function (and by extension, the\n ``str.format()`` method of class ``str``) to produce a "formatted"\n string representation of an object. The ``format_spec`` argument is\n a string that contains a description of the formatting options\n desired. The interpretation of the ``format_spec`` argument is up\n to the type implementing ``__format__()``, however most classes\n will either delegate formatting to one of the built-in types, or\n use a similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: ``xy`` calls ``x.__gt__(y)``, and ``x>=y`` calls\n ``x.__ge__(y)``.\n\n A rich comparison method may return the singleton\n ``NotImplemented`` if it does not implement the operation for a\n given pair of arguments. By convention, ``False`` and ``True`` are\n returned for a successful comparison. However, these methods can\n return any value, so if the comparison operator is used in a\n Boolean context (e.g., in the condition of an ``if`` statement),\n Python will call ``bool()`` on the value to determine if the result\n is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of ``x==y`` does not imply that ``x!=y`` is false.\n Accordingly, when defining ``__eq__()``, one should also define\n ``__ne__()`` so that the operators will behave as expected. See\n the paragraph on ``__hash__()`` for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, ``__lt__()`` and ``__gt__()`` are each\n other\'s reflection, ``__le__()`` and ``__ge__()`` are each other\'s\n reflection, and ``__eq__()`` and ``__ne__()`` are their own\n reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see ``functools.total_ordering()``.\n\nobject.__hash__(self)\n\n Called by built-in function ``hash()`` and for operations on\n members of hashed collections including ``set``, ``frozenset``, and\n ``dict``. ``__hash__()`` should return an integer. The only\n required property is that objects which compare equal have the same\n hash value; it is advised to somehow mix together (e.g. using\n exclusive or) the hash values for the components of the object that\n also play a part in comparison of objects.\n\n Note: ``hash()`` truncates the value returned from an object\'s custom\n ``__hash__()`` method to the size of a ``Py_ssize_t``. This is\n typically 8 bytes on 64-bit builds and 4 bytes on 32-bit builds.\n If an object\'s ``__hash__()`` must interoperate on builds of\n different bit sizes, be sure to check the width on all supported\n builds. An easy way to do this is with ``python -c "import sys;\n print(sys.hash_info.width)"``\n\n If a class does not define an ``__eq__()`` method it should not\n define a ``__hash__()`` operation either; if it defines\n ``__eq__()`` but not ``__hash__()``, its instances will not be\n usable as items in hashable collections. If a class defines\n mutable objects and implements an ``__eq__()`` method, it should\n not implement ``__hash__()``, since the implementation of hashable\n collections requires that a key\'s hash value is immutable (if the\n object\'s hash value changes, it will be in the wrong hash bucket).\n\n User-defined classes have ``__eq__()`` and ``__hash__()`` methods\n by default; with them, all objects compare unequal (except with\n themselves) and ``x.__hash__()`` returns an appropriate value such\n that ``x == y`` implies both that ``x is y`` and ``hash(x) ==\n hash(y)``.\n\n A class that overrides ``__eq__()`` and does not define\n ``__hash__()`` will have its ``__hash__()`` implicitly set to\n ``None``. When the ``__hash__()`` method of a class is ``None``,\n instances of the class will raise an appropriate ``TypeError`` when\n a program attempts to retrieve their hash value, and will also be\n correctly identified as unhashable when checking ``isinstance(obj,\n collections.Hashable``).\n\n If a class that overrides ``__eq__()`` needs to retain the\n implementation of ``__hash__()`` from a parent class, the\n interpreter must be told this explicitly by setting ``__hash__ =\n .__hash__``.\n\n If a class that does not override ``__eq__()`` wishes to suppress\n hash support, it should include ``__hash__ = None`` in the class\n definition. A class which defines its own ``__hash__()`` that\n explicitly raises a ``TypeError`` would be incorrectly identified\n as hashable by an ``isinstance(obj, collections.Hashable)`` call.\n\n Note: By default, the ``__hash__()`` values of str, bytes and datetime\n objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also ``PYTHONHASHSEED``.\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n ``bool()``; should return ``False`` or ``True``. When this method\n is not defined, ``__len__()`` is called, if it is defined, and the\n object is considered true if its result is nonzero. If a class\n defines neither ``__len__()`` nor ``__bool__()``, all its instances\n are considered true.\n', - 'debugger': '\n``pdb`` --- The Python Debugger\n*******************************\n\nThe module ``pdb`` defines an interactive source code debugger for\nPython programs. It supports setting (conditional) breakpoints and\nsingle stepping at the source line level, inspection of stack frames,\nsource code listing, and evaluation of arbitrary Python code in the\ncontext of any stack frame. It also supports post-mortem debugging\nand can be called under program control.\n\nThe debugger is extensible -- it is actually defined as the class\n``Pdb``. This is currently undocumented but easily understood by\nreading the source. The extension interface uses the modules ``bdb``\nand ``cmd``.\n\nThe debugger\'s prompt is ``(Pdb)``. Typical usage to run a program\nunder control of the debugger is:\n\n >>> import pdb\n >>> import mymodule\n >>> pdb.run(\'mymodule.test()\')\n > (0)?()\n (Pdb) continue\n > (1)?()\n (Pdb) continue\n NameError: \'spam\'\n > (1)?()\n (Pdb)\n\nChanged in version 3.3: Tab-completion via the ``readline`` module is\navailable for commands and command arguments, e.g. the current global\nand local names are offered as arguments of the ``print`` command.\n\n``pdb.py`` can also be invoked as a script to debug other scripts.\nFor example:\n\n python3 -m pdb myscript.py\n\nWhen invoked as a script, pdb will automatically enter post-mortem\ndebugging if the program being debugged exits abnormally. After post-\nmortem debugging (or after normal exit of the program), pdb will\nrestart the program. Automatic restarting preserves pdb\'s state (such\nas breakpoints) and in most cases is more useful than quitting the\ndebugger upon program\'s exit.\n\nNew in version 3.2: ``pdb.py`` now accepts a ``-c`` option that\nexecutes commands as if given in a ``.pdbrc`` file, see *Debugger\nCommands*.\n\nThe typical usage to break into the debugger from a running program is\nto insert\n\n import pdb; pdb.set_trace()\n\nat the location you want to break into the debugger. You can then\nstep through the code following this statement, and continue running\nwithout the debugger using the ``continue`` command.\n\nThe typical usage to inspect a crashed program is:\n\n >>> import pdb\n >>> import mymodule\n >>> mymodule.test()\n Traceback (most recent call last):\n File "", line 1, in ?\n File "./mymodule.py", line 4, in test\n test2()\n File "./mymodule.py", line 3, in test2\n print(spam)\n NameError: spam\n >>> pdb.pm()\n > ./mymodule.py(3)test2()\n -> print(spam)\n (Pdb)\n\nThe module defines the following functions; each enters the debugger\nin a slightly different way:\n\npdb.run(statement, globals=None, locals=None)\n\n Execute the *statement* (given as a string or a code object) under\n debugger control. The debugger prompt appears before any code is\n executed; you can set breakpoints and type ``continue``, or you can\n step through the statement using ``step`` or ``next`` (all these\n commands are explained below). The optional *globals* and *locals*\n arguments specify the environment in which the code is executed; by\n default the dictionary of the module ``__main__`` is used. (See\n the explanation of the built-in ``exec()`` or ``eval()``\n functions.)\n\npdb.runeval(expression, globals=None, locals=None)\n\n Evaluate the *expression* (given as a string or a code object)\n under debugger control. When ``runeval()`` returns, it returns the\n value of the expression. Otherwise this function is similar to\n ``run()``.\n\npdb.runcall(function, *args, **kwds)\n\n Call the *function* (a function or method object, not a string)\n with the given arguments. When ``runcall()`` returns, it returns\n whatever the function call returned. The debugger prompt appears\n as soon as the function is entered.\n\npdb.set_trace()\n\n Enter the debugger at the calling stack frame. This is useful to\n hard-code a breakpoint at a given point in a program, even if the\n code is not otherwise being debugged (e.g. when an assertion\n fails).\n\npdb.post_mortem(traceback=None)\n\n Enter post-mortem debugging of the given *traceback* object. If no\n *traceback* is given, it uses the one of the exception that is\n currently being handled (an exception must be being handled if the\n default is to be used).\n\npdb.pm()\n\n Enter post-mortem debugging of the traceback found in\n ``sys.last_traceback``.\n\nThe ``run*`` functions and ``set_trace()`` are aliases for\ninstantiating the ``Pdb`` class and calling the method of the same\nname. If you want to access further features, you have to do this\nyourself:\n\nclass class pdb.Pdb(completekey=\'tab\', stdin=None, stdout=None, skip=None, nosigint=False)\n\n ``Pdb`` is the debugger class.\n\n The *completekey*, *stdin* and *stdout* arguments are passed to the\n underlying ``cmd.Cmd`` class; see the description there.\n\n The *skip* argument, if given, must be an iterable of glob-style\n module name patterns. The debugger will not step into frames that\n originate in a module that matches one of these patterns. [1]\n\n By default, Pdb sets a handler for the SIGINT signal (which is sent\n when the user presses Ctrl-C on the console) when you give a\n ``continue`` command. This allows you to break into the debugger\n again by pressing Ctrl-C. If you want Pdb not to touch the SIGINT\n handler, set *nosigint* tot true.\n\n Example call to enable tracing with *skip*:\n\n import pdb; pdb.Pdb(skip=[\'django.*\']).set_trace()\n\n New in version 3.1: The *skip* argument.\n\n New in version 3.2: The *nosigint* argument. Previously, a SIGINT\n handler was never set by Pdb.\n\n run(statement, globals=None, locals=None)\n runeval(expression, globals=None, locals=None)\n runcall(function, *args, **kwds)\n set_trace()\n\n See the documentation for the functions explained above.\n\n\nDebugger Commands\n=================\n\nThe commands recognized by the debugger are listed below. Most\ncommands can be abbreviated to one or two letters as indicated; e.g.\n``h(elp)`` means that either ``h`` or ``help`` can be used to enter\nthe help command (but not ``he`` or ``hel``, nor ``H`` or ``Help`` or\n``HELP``). Arguments to commands must be separated by whitespace\n(spaces or tabs). Optional arguments are enclosed in square brackets\n(``[]``) in the command syntax; the square brackets must not be typed.\nAlternatives in the command syntax are separated by a vertical bar\n(``|``).\n\nEntering a blank line repeats the last command entered. Exception: if\nthe last command was a ``list`` command, the next 11 lines are listed.\n\nCommands that the debugger doesn\'t recognize are assumed to be Python\nstatements and are executed in the context of the program being\ndebugged. Python statements can also be prefixed with an exclamation\npoint (``!``). This is a powerful way to inspect the program being\ndebugged; it is even possible to change a variable or call a function.\nWhen an exception occurs in such a statement, the exception name is\nprinted but the debugger\'s state is not changed.\n\nThe debugger supports *aliases*. Aliases can have parameters which\nallows one a certain level of adaptability to the context under\nexamination.\n\nMultiple commands may be entered on a single line, separated by\n``;;``. (A single ``;`` is not used as it is the separator for\nmultiple commands in a line that is passed to the Python parser.) No\nintelligence is applied to separating the commands; the input is split\nat the first ``;;`` pair, even if it is in the middle of a quoted\nstring.\n\nIf a file ``.pdbrc`` exists in the user\'s home directory or in the\ncurrent directory, it is read in and executed as if it had been typed\nat the debugger prompt. This is particularly useful for aliases. If\nboth files exist, the one in the home directory is read first and\naliases defined there can be overridden by the local file.\n\nChanged in version 3.2: ``.pdbrc`` can now contain commands that\ncontinue debugging, such as ``continue`` or ``next``. Previously,\nthese commands had no effect.\n\nh(elp) [command]\n\n Without argument, print the list of available commands. With a\n *command* as argument, print help about that command. ``help pdb``\n displays the full documentation (the docstring of the ``pdb``\n module). Since the *command* argument must be an identifier,\n ``help exec`` must be entered to get help on the ``!`` command.\n\nw(here)\n\n Print a stack trace, with the most recent frame at the bottom. An\n arrow indicates the current frame, which determines the context of\n most commands.\n\nd(own) [count]\n\n Move the current frame *count* (default one) levels down in the\n stack trace (to a newer frame).\n\nu(p) [count]\n\n Move the current frame *count* (default one) levels up in the stack\n trace (to an older frame).\n\nb(reak) [([filename:]lineno | function) [, condition]]\n\n With a *lineno* argument, set a break there in the current file.\n With a *function* argument, set a break at the first executable\n statement within that function. The line number may be prefixed\n with a filename and a colon, to specify a breakpoint in another\n file (probably one that hasn\'t been loaded yet). The file is\n searched on ``sys.path``. Note that each breakpoint is assigned a\n number to which all the other breakpoint commands refer.\n\n If a second argument is present, it is an expression which must\n evaluate to true before the breakpoint is honored.\n\n Without argument, list all breaks, including for each breakpoint,\n the number of times that breakpoint has been hit, the current\n ignore count, and the associated condition if any.\n\ntbreak [([filename:]lineno | function) [, condition]]\n\n Temporary breakpoint, which is removed automatically when it is\n first hit. The arguments are the same as for ``break``.\n\ncl(ear) [filename:lineno | bpnumber [bpnumber ...]]\n\n With a *filename:lineno* argument, clear all the breakpoints at\n this line. With a space separated list of breakpoint numbers, clear\n those breakpoints. Without argument, clear all breaks (but first\n ask confirmation).\n\ndisable [bpnumber [bpnumber ...]]\n\n Disable the breakpoints given as a space separated list of\n breakpoint numbers. Disabling a breakpoint means it cannot cause\n the program to stop execution, but unlike clearing a breakpoint, it\n remains in the list of breakpoints and can be (re-)enabled.\n\nenable [bpnumber [bpnumber ...]]\n\n Enable the breakpoints specified.\n\nignore bpnumber [count]\n\n Set the ignore count for the given breakpoint number. If count is\n omitted, the ignore count is set to 0. A breakpoint becomes active\n when the ignore count is zero. When non-zero, the count is\n decremented each time the breakpoint is reached and the breakpoint\n is not disabled and any associated condition evaluates to true.\n\ncondition bpnumber [condition]\n\n Set a new *condition* for the breakpoint, an expression which must\n evaluate to true before the breakpoint is honored. If *condition*\n is absent, any existing condition is removed; i.e., the breakpoint\n is made unconditional.\n\ncommands [bpnumber]\n\n Specify a list of commands for breakpoint number *bpnumber*. The\n commands themselves appear on the following lines. Type a line\n containing just ``end`` to terminate the commands. An example:\n\n (Pdb) commands 1\n (com) print some_variable\n (com) end\n (Pdb)\n\n To remove all commands from a breakpoint, type commands and follow\n it immediately with ``end``; that is, give no commands.\n\n With no *bpnumber* argument, commands refers to the last breakpoint\n set.\n\n You can use breakpoint commands to start your program up again.\n Simply use the continue command, or step, or any other command that\n resumes execution.\n\n Specifying any command resuming execution (currently continue,\n step, next, return, jump, quit and their abbreviations) terminates\n the command list (as if that command was immediately followed by\n end). This is because any time you resume execution (even with a\n simple next or step), you may encounter another breakpoint--which\n could have its own command list, leading to ambiguities about which\n list to execute.\n\n If you use the \'silent\' command in the command list, the usual\n message about stopping at a breakpoint is not printed. This may be\n desirable for breakpoints that are to print a specific message and\n then continue. If none of the other commands print anything, you\n see no sign that the breakpoint was reached.\n\ns(tep)\n\n Execute the current line, stop at the first possible occasion\n (either in a function that is called or on the next line in the\n current function).\n\nn(ext)\n\n Continue execution until the next line in the current function is\n reached or it returns. (The difference between ``next`` and\n ``step`` is that ``step`` stops inside a called function, while\n ``next`` executes called functions at (nearly) full speed, only\n stopping at the next line in the current function.)\n\nunt(il) [lineno]\n\n Without argument, continue execution until the line with a number\n greater than the current one is reached.\n\n With a line number, continue execution until a line with a number\n greater or equal to that is reached. In both cases, also stop when\n the current frame returns.\n\n Changed in version 3.2: Allow giving an explicit line number.\n\nr(eturn)\n\n Continue execution until the current function returns.\n\nc(ont(inue))\n\n Continue execution, only stop when a breakpoint is encountered.\n\nj(ump) lineno\n\n Set the next line that will be executed. Only available in the\n bottom-most frame. This lets you jump back and execute code again,\n or jump forward to skip code that you don\'t want to run.\n\n It should be noted that not all jumps are allowed -- for instance\n it is not possible to jump into the middle of a ``for`` loop or out\n of a ``finally`` clause.\n\nl(ist) [first[, last]]\n\n List source code for the current file. Without arguments, list 11\n lines around the current line or continue the previous listing.\n With ``.`` as argument, list 11 lines around the current line.\n With one argument, list 11 lines around at that line. With two\n arguments, list the given range; if the second argument is less\n than the first, it is interpreted as a count.\n\n The current line in the current frame is indicated by ``->``. If\n an exception is being debugged, the line where the exception was\n originally raised or propagated is indicated by ``>>``, if it\n differs from the current line.\n\n New in version 3.2: The ``>>`` marker.\n\nll | longlist\n\n List all source code for the current function or frame.\n Interesting lines are marked as for ``list``.\n\n New in version 3.2.\n\na(rgs)\n\n Print the argument list of the current function.\n\np(rint) expression\n\n Evaluate the *expression* in the current context and print its\n value.\n\npp expression\n\n Like the ``print`` command, except the value of the expression is\n pretty-printed using the ``pprint`` module.\n\nwhatis expression\n\n Print the type of the *expression*.\n\nsource expression\n\n Try to get source code for the given object and display it.\n\n New in version 3.2.\n\ndisplay [expression]\n\n Display the value of the expression if it changed, each time\n execution stops in the current frame.\n\n Without expression, list all display expressions for the current\n frame.\n\n New in version 3.2.\n\nundisplay [expression]\n\n Do not display the expression any more in the current frame.\n Without expression, clear all display expressions for the current\n frame.\n\n New in version 3.2.\n\ninteract\n\n Start an interative interpreter (using the ``code`` module) whose\n global namespace contains all the (global and local) names found in\n the current scope.\n\n New in version 3.2.\n\nalias [name [command]]\n\n Create an alias called *name* that executes *command*. The command\n must *not* be enclosed in quotes. Replaceable parameters can be\n indicated by ``%1``, ``%2``, and so on, while ``%*`` is replaced by\n all the parameters. If no command is given, the current alias for\n *name* is shown. If no arguments are given, all aliases are listed.\n\n Aliases may be nested and can contain anything that can be legally\n typed at the pdb prompt. Note that internal pdb commands *can* be\n overridden by aliases. Such a command is then hidden until the\n alias is removed. Aliasing is recursively applied to the first\n word of the command line; all other words in the line are left\n alone.\n\n As an example, here are two useful aliases (especially when placed\n in the ``.pdbrc`` file):\n\n # Print instance variables (usage "pi classInst")\n alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k])\n # Print instance variables in self\n alias ps pi self\n\nunalias name\n\n Delete the specified alias.\n\n! statement\n\n Execute the (one-line) *statement* in the context of the current\n stack frame. The exclamation point can be omitted unless the first\n word of the statement resembles a debugger command. To set a\n global variable, you can prefix the assignment command with a\n ``global`` statement on the same line, e.g.:\n\n (Pdb) global list_options; list_options = [\'-l\']\n (Pdb)\n\nrun [args ...]\nrestart [args ...]\n\n Restart the debugged Python program. If an argument is supplied,\n it is split with ``shlex`` and the result is used as the new\n ``sys.argv``. History, breakpoints, actions and debugger options\n are preserved. ``restart`` is an alias for ``run``.\n\nq(uit)\n\n Quit from the debugger. The program being executed is aborted.\n\n-[ Footnotes ]-\n\n[1] Whether a frame is considered to originate in a certain module is\n determined by the ``__name__`` in the frame globals.\n', - 'del': '\nThe ``del`` statement\n*********************\n\n del_stmt ::= "del" target_list\n\nDeletion is recursively defined very similar to the way assignment is\ndefined. Rather than spelling it out in full details, here are some\nhints.\n\nDeletion of a target list recursively deletes each target, from left\nto right.\n\nDeletion of a name removes the binding of that name from the local or\nglobal namespace, depending on whether the name occurs in a ``global``\nstatement in the same code block. If the name is unbound, a\n``NameError`` exception will be raised.\n\nDeletion of attribute references, subscriptions and slicings is passed\nto the primary object involved; deletion of a slicing is in general\nequivalent to assignment of an empty slice of the right type (but even\nthis is determined by the sliced object).\n\nChanged in version 3.2: Previously it was illegal to delete a name\nfrom the local namespace if it occurs as a free variable in a nested\nblock.\n', + 'attribute-access': '\nCustomizing attribute access\n****************************\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n========================\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n====================\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n=========\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n class, *__slots__* reserves space for the declared variables and\n prevents the automatic creation of *__dict__* and *__weakref__* for\n each instance.\n\n\nNotes on using *__slots__*\n--------------------------\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n', + 'attribute-references': '\nAttribute references\n********************\n\nAn attribute reference is a primary followed by a period and a name:\n\n attributeref ::= primary "." identifier\n\nThe primary must evaluate to an object of a type that supports\nattribute references, which most objects do. This object is then\nasked to produce the attribute whose name is the identifier (which can\nbe customized by overriding the "__getattr__()" method). If this\nattribute is not available, the exception "AttributeError" is raised.\nOtherwise, the type and value of the object produced is determined by\nthe object. Multiple evaluations of the same attribute reference may\nyield different objects.\n', + 'augassign': '\nAugmented assignment statements\n*******************************\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', + 'binary': '\nBinary arithmetic operations\n****************************\n\nThe binary arithmetic operations have the conventional priority\nlevels. Note that some of these operations also apply to certain non-\nnumeric types. Apart from the power operator, there are only two\nlevels, one for multiplicative operators and one for additive\noperators:\n\n m_expr ::= u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr\n | m_expr "%" u_expr\n a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr\n\nThe "*" (multiplication) operator yields the product of its arguments.\nThe arguments must either both be numbers, or one argument must be an\ninteger and the other must be a sequence. In the former case, the\nnumbers are converted to a common type and then multiplied together.\nIn the latter case, sequence repetition is performed; a negative\nrepetition factor yields an empty sequence.\n\nThe "/" (division) and "//" (floor division) operators yield the\nquotient of their arguments. The numeric arguments are first\nconverted to a common type. Division of integers yields a float, while\nfloor division of integers results in an integer; the result is that\nof mathematical division with the \'floor\' function applied to the\nresult. Division by zero raises the "ZeroDivisionError" exception.\n\nThe "%" (modulo) operator yields the remainder from the division of\nthe first argument by the second. The numeric arguments are first\nconverted to a common type. A zero right argument raises the\n"ZeroDivisionError" exception. The arguments may be floating point\nnumbers, e.g., "3.14%0.7" equals "0.34" (since "3.14" equals "4*0.7 +\n0.34".) The modulo operator always yields a result with the same sign\nas its second operand (or zero); the absolute value of the result is\nstrictly smaller than the absolute value of the second operand [1].\n\nThe floor division and modulo operators are connected by the following\nidentity: "x == (x//y)*y + (x%y)". Floor division and modulo are also\nconnected with the built-in function "divmod()": "divmod(x, y) ==\n(x//y, x%y)". [2].\n\nIn addition to performing the modulo operation on numbers, the "%"\noperator is also overloaded by string objects to perform old-style\nstring formatting (also known as interpolation). The syntax for\nstring formatting is described in the Python Library Reference,\nsection *printf-style String Formatting*.\n\nThe floor division operator, the modulo operator, and the "divmod()"\nfunction are not defined for complex numbers. Instead, convert to a\nfloating point number using the "abs()" function if appropriate.\n\nThe "+" (addition) operator yields the sum of its arguments. The\narguments must either both be numbers or both sequences of the same\ntype. In the former case, the numbers are converted to a common type\nand then added together. In the latter case, the sequences are\nconcatenated.\n\nThe "-" (subtraction) operator yields the difference of its arguments.\nThe numeric arguments are first converted to a common type.\n', + 'bitwise': '\nBinary bitwise operations\n*************************\n\nEach of the three bitwise operations has a different priority level:\n\n and_expr ::= shift_expr | and_expr "&" shift_expr\n xor_expr ::= and_expr | xor_expr "^" and_expr\n or_expr ::= xor_expr | or_expr "|" xor_expr\n\nThe "&" operator yields the bitwise AND of its arguments, which must\nbe integers.\n\nThe "^" operator yields the bitwise XOR (exclusive OR) of its\narguments, which must be integers.\n\nThe "|" operator yields the bitwise (inclusive) OR of its arguments,\nwhich must be integers.\n', + 'bltin-code-objects': '\nCode Objects\n************\n\nCode objects are used by the implementation to represent "pseudo-\ncompiled" executable Python code such as a function body. They differ\nfrom function objects because they don\'t contain a reference to their\nglobal execution environment. Code objects are returned by the built-\nin "compile()" function and can be extracted from function objects\nthrough their "__code__" attribute. See also the "code" module.\n\nA code object can be executed or evaluated by passing it (instead of a\nsource string) to the "exec()" or "eval()" built-in functions.\n\nSee *The standard type hierarchy* for more information.\n', + 'bltin-ellipsis-object': '\nThe Ellipsis Object\n*******************\n\nThis object is commonly used by slicing (see *Slicings*). It supports\nno special operations. There is exactly one ellipsis object, named\n"Ellipsis" (a built-in name). "type(Ellipsis)()" produces the\n"Ellipsis" singleton.\n\nIt is written as "Ellipsis" or "...".\n', + 'bltin-null-object': '\nThe Null Object\n***************\n\nThis object is returned by functions that don\'t explicitly return a\nvalue. It supports no special operations. There is exactly one null\nobject, named "None" (a built-in name). "type(None)()" produces the\nsame singleton.\n\nIt is written as "None".\n', + 'bltin-type-objects': '\nType Objects\n************\n\nType objects represent the various object types. An object\'s type is\naccessed by the built-in function "type()". There are no special\noperations on types. The standard module "types" defines names for\nall standard built-in types.\n\nTypes are written like this: "".\n', + 'booleans': '\nBoolean operations\n******************\n\n or_test ::= and_test | or_test "or" and_test\n and_test ::= not_test | and_test "and" not_test\n not_test ::= comparison | "not" not_test\n\nIn the context of Boolean operations, and also when expressions are\nused by control flow statements, the following values are interpreted\nas false: "False", "None", numeric zero of all types, and empty\nstrings and containers (including strings, tuples, lists,\ndictionaries, sets and frozensets). All other values are interpreted\nas true. User-defined objects can customize their truth value by\nproviding a "__bool__()" method.\n\nThe operator "not" yields "True" if its argument is false, "False"\notherwise.\n\nThe expression "x and y" first evaluates *x*; if *x* is false, its\nvalue is returned; otherwise, *y* is evaluated and the resulting value\nis returned.\n\nThe expression "x or y" first evaluates *x*; if *x* is true, its value\nis returned; otherwise, *y* is evaluated and the resulting value is\nreturned.\n\n(Note that neither "and" nor "or" restrict the value and type they\nreturn to "False" and "True", but rather return the last evaluated\nargument. This is sometimes useful, e.g., if "s" is a string that\nshould be replaced by a default value if it is empty, the expression\n"s or \'foo\'" yields the desired value. Because "not" has to invent a\nvalue anyway, it does not bother to return a value of the same type as\nits argument, so e.g., "not \'foo\'" yields "False", not "\'\'".)\n', + 'break': '\nThe "break" statement\n*********************\n\n break_stmt ::= "break"\n\n"break" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition within that\nloop.\n\nIt terminates the nearest enclosing loop, skipping the optional "else"\nclause if the loop has one.\n\nIf a "for" loop is terminated by "break", the loop control target\nkeeps its current value.\n\nWhen "break" passes control out of a "try" statement with a "finally"\nclause, that "finally" clause is executed before really leaving the\nloop.\n', + 'callable-types': '\nEmulating callable objects\n**************************\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n', + 'calls': '\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","] | comprehension] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," keyword_arguments] ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nA trailing comma may be present after the positional and keyword\narguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and all objects having a\n"__call__()" method are callable). All argument expressions are\nevaluated before the call is attempted. Please refer to section\n*Function definitions* for the syntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a "TypeError" exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is "None", it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a "TypeError"\nexception is raised. Otherwise, the list of filled slots is used as\nthe argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use "PyArg_ParseTuple()" to parse\ntheir arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "*identifier" is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "**identifier" is present; in this case, that formal\nparameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax "*expression" appears in the function call, "expression"\nmust evaluate to an iterable. Elements from this iterable are treated\nas if they were additional positional arguments; if there are\npositional arguments *x1*, ..., *xN*, and "expression" evaluates to a\nsequence *y1*, ..., *yM*, this is equivalent to a call with M+N\npositional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the "*expression" syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the "**expression" argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print(a, b)\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the "*expression" syntax\nto be used in the same call, so in practice this confusion does not\narise.\n\nIf the syntax "**expression" appears in the function call,\n"expression" must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both "expression" and as an explicit keyword argument, a\n"TypeError" exception is raised.\n\nFormal parameters using the syntax "*identifier" or "**identifier"\ncannot be used as positional argument slots or as keyword argument\nnames.\n\nA call always returns some value, possibly "None", unless it raises an\nexception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a "return"\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a "__call__()" method; the effect is then the\n same as if that method was called.\n', + 'class': '\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'comparisons': '\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. The\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of the differing types depends on whether either\nof the types provide explicit support for the comparison. Most\nnumeric types can be compared with one another. When cross-type\ncomparison is not supported, the comparison method returns\n"NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether a the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', + 'compound': '\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nCompound statements consist of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there was no next\nitem.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" target]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be access via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n def f():\n try:\n 1/0\n finally:\n return 42\n\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use "None" as the default,\nand explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'context-managers': '\nWith Statement Context Managers\n*******************************\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', + 'continue': '\nThe "continue" statement\n************************\n\n continue_stmt ::= "continue"\n\n"continue" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition or "finally"\nclause within that loop. It continues with the next cycle of the\nnearest enclosing loop.\n\nWhen "continue" passes control out of a "try" statement with a\n"finally" clause, that "finally" clause is executed before really\nstarting the next loop cycle.\n', + 'conversions': '\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," this means\nthat the operator implementation for built-in types works that way:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the\n other is converted to floating point;\n\n* otherwise, both must be integers and no conversion is necessary.\n\nSome additional rules apply for certain operators (e.g., a string left\nargument to the \'%\' operator). Extensions must define their own\nconversion behavior.\n', + 'customization': '\nBasic customization\n*******************\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called when the instance is created. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])". As a special constraint on\n constructors, no value may be returned; doing so will cause a\n "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing "None" in\n "sys.last_traceback". Circular references which are garbage are\n detected when the option cycle detector is enabled (it\'s on by\n default), but can only be cleaned up if there are no Python-\n level "__del__()" methods involved. Refer to the documentation\n for the "gc" module for more information about how "__del__()"\n methods are handled by the cycle detector, particularly the\n description of the "garbage" value.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)""\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable").\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n .__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n', + 'debugger': '\n"pdb" --- The Python Debugger\n*****************************\n\nThe module "pdb" defines an interactive source code debugger for\nPython programs. It supports setting (conditional) breakpoints and\nsingle stepping at the source line level, inspection of stack frames,\nsource code listing, and evaluation of arbitrary Python code in the\ncontext of any stack frame. It also supports post-mortem debugging\nand can be called under program control.\n\nThe debugger is extensible -- it is actually defined as the class\n"Pdb". This is currently undocumented but easily understood by reading\nthe source. The extension interface uses the modules "bdb" and "cmd".\n\nThe debugger\'s prompt is "(Pdb)". Typical usage to run a program under\ncontrol of the debugger is:\n\n >>> import pdb\n >>> import mymodule\n >>> pdb.run(\'mymodule.test()\')\n > (0)?()\n (Pdb) continue\n > (1)?()\n (Pdb) continue\n NameError: \'spam\'\n > (1)?()\n (Pdb)\n\nChanged in version 3.3: Tab-completion via the "readline" module is\navailable for commands and command arguments, e.g. the current global\nand local names are offered as arguments of the "print" command.\n\n"pdb.py" can also be invoked as a script to debug other scripts. For\nexample:\n\n python3 -m pdb myscript.py\n\nWhen invoked as a script, pdb will automatically enter post-mortem\ndebugging if the program being debugged exits abnormally. After post-\nmortem debugging (or after normal exit of the program), pdb will\nrestart the program. Automatic restarting preserves pdb\'s state (such\nas breakpoints) and in most cases is more useful than quitting the\ndebugger upon program\'s exit.\n\nNew in version 3.2: "pdb.py" now accepts a "-c" option that executes\ncommands as if given in a ".pdbrc" file, see *Debugger Commands*.\n\nThe typical usage to break into the debugger from a running program is\nto insert\n\n import pdb; pdb.set_trace()\n\nat the location you want to break into the debugger. You can then\nstep through the code following this statement, and continue running\nwithout the debugger using the "continue" command.\n\nThe typical usage to inspect a crashed program is:\n\n >>> import pdb\n >>> import mymodule\n >>> mymodule.test()\n Traceback (most recent call last):\n File "", line 1, in ?\n File "./mymodule.py", line 4, in test\n test2()\n File "./mymodule.py", line 3, in test2\n print(spam)\n NameError: spam\n >>> pdb.pm()\n > ./mymodule.py(3)test2()\n -> print(spam)\n (Pdb)\n\nThe module defines the following functions; each enters the debugger\nin a slightly different way:\n\npdb.run(statement, globals=None, locals=None)\n\n Execute the *statement* (given as a string or a code object) under\n debugger control. The debugger prompt appears before any code is\n executed; you can set breakpoints and type "continue", or you can\n step through the statement using "step" or "next" (all these\n commands are explained below). The optional *globals* and *locals*\n arguments specify the environment in which the code is executed; by\n default the dictionary of the module "__main__" is used. (See the\n explanation of the built-in "exec()" or "eval()" functions.)\n\npdb.runeval(expression, globals=None, locals=None)\n\n Evaluate the *expression* (given as a string or a code object)\n under debugger control. When "runeval()" returns, it returns the\n value of the expression. Otherwise this function is similar to\n "run()".\n\npdb.runcall(function, *args, **kwds)\n\n Call the *function* (a function or method object, not a string)\n with the given arguments. When "runcall()" returns, it returns\n whatever the function call returned. The debugger prompt appears\n as soon as the function is entered.\n\npdb.set_trace()\n\n Enter the debugger at the calling stack frame. This is useful to\n hard-code a breakpoint at a given point in a program, even if the\n code is not otherwise being debugged (e.g. when an assertion\n fails).\n\npdb.post_mortem(traceback=None)\n\n Enter post-mortem debugging of the given *traceback* object. If no\n *traceback* is given, it uses the one of the exception that is\n currently being handled (an exception must be being handled if the\n default is to be used).\n\npdb.pm()\n\n Enter post-mortem debugging of the traceback found in\n "sys.last_traceback".\n\nThe "run*" functions and "set_trace()" are aliases for instantiating\nthe "Pdb" class and calling the method of the same name. If you want\nto access further features, you have to do this yourself:\n\nclass class pdb.Pdb(completekey=\'tab\', stdin=None, stdout=None, skip=None, nosigint=False)\n\n "Pdb" is the debugger class.\n\n The *completekey*, *stdin* and *stdout* arguments are passed to the\n underlying "cmd.Cmd" class; see the description there.\n\n The *skip* argument, if given, must be an iterable of glob-style\n module name patterns. The debugger will not step into frames that\n originate in a module that matches one of these patterns. [1]\n\n By default, Pdb sets a handler for the SIGINT signal (which is sent\n when the user presses Ctrl-C on the console) when you give a\n "continue" command. This allows you to break into the debugger\n again by pressing Ctrl-C. If you want Pdb not to touch the SIGINT\n handler, set *nosigint* tot true.\n\n Example call to enable tracing with *skip*:\n\n import pdb; pdb.Pdb(skip=[\'django.*\']).set_trace()\n\n New in version 3.1: The *skip* argument.\n\n New in version 3.2: The *nosigint* argument. Previously, a SIGINT\n handler was never set by Pdb.\n\n run(statement, globals=None, locals=None)\n runeval(expression, globals=None, locals=None)\n runcall(function, *args, **kwds)\n set_trace()\n\n See the documentation for the functions explained above.\n\n\nDebugger Commands\n=================\n\nThe commands recognized by the debugger are listed below. Most\ncommands can be abbreviated to one or two letters as indicated; e.g.\n"h(elp)" means that either "h" or "help" can be used to enter the help\ncommand (but not "he" or "hel", nor "H" or "Help" or "HELP").\nArguments to commands must be separated by whitespace (spaces or\ntabs). Optional arguments are enclosed in square brackets ("[]") in\nthe command syntax; the square brackets must not be typed.\nAlternatives in the command syntax are separated by a vertical bar\n("|").\n\nEntering a blank line repeats the last command entered. Exception: if\nthe last command was a "list" command, the next 11 lines are listed.\n\nCommands that the debugger doesn\'t recognize are assumed to be Python\nstatements and are executed in the context of the program being\ndebugged. Python statements can also be prefixed with an exclamation\npoint ("!"). This is a powerful way to inspect the program being\ndebugged; it is even possible to change a variable or call a function.\nWhen an exception occurs in such a statement, the exception name is\nprinted but the debugger\'s state is not changed.\n\nThe debugger supports *aliases*. Aliases can have parameters which\nallows one a certain level of adaptability to the context under\nexamination.\n\nMultiple commands may be entered on a single line, separated by ";;".\n(A single ";" is not used as it is the separator for multiple commands\nin a line that is passed to the Python parser.) No intelligence is\napplied to separating the commands; the input is split at the first\n";;" pair, even if it is in the middle of a quoted string.\n\nIf a file ".pdbrc" exists in the user\'s home directory or in the\ncurrent directory, it is read in and executed as if it had been typed\nat the debugger prompt. This is particularly useful for aliases. If\nboth files exist, the one in the home directory is read first and\naliases defined there can be overridden by the local file.\n\nChanged in version 3.2: ".pdbrc" can now contain commands that\ncontinue debugging, such as "continue" or "next". Previously, these\ncommands had no effect.\n\nh(elp) [command]\n\n Without argument, print the list of available commands. With a\n *command* as argument, print help about that command. "help pdb"\n displays the full documentation (the docstring of the "pdb"\n module). Since the *command* argument must be an identifier, "help\n exec" must be entered to get help on the "!" command.\n\nw(here)\n\n Print a stack trace, with the most recent frame at the bottom. An\n arrow indicates the current frame, which determines the context of\n most commands.\n\nd(own) [count]\n\n Move the current frame *count* (default one) levels down in the\n stack trace (to a newer frame).\n\nu(p) [count]\n\n Move the current frame *count* (default one) levels up in the stack\n trace (to an older frame).\n\nb(reak) [([filename:]lineno | function) [, condition]]\n\n With a *lineno* argument, set a break there in the current file.\n With a *function* argument, set a break at the first executable\n statement within that function. The line number may be prefixed\n with a filename and a colon, to specify a breakpoint in another\n file (probably one that hasn\'t been loaded yet). The file is\n searched on "sys.path". Note that each breakpoint is assigned a\n number to which all the other breakpoint commands refer.\n\n If a second argument is present, it is an expression which must\n evaluate to true before the breakpoint is honored.\n\n Without argument, list all breaks, including for each breakpoint,\n the number of times that breakpoint has been hit, the current\n ignore count, and the associated condition if any.\n\ntbreak [([filename:]lineno | function) [, condition]]\n\n Temporary breakpoint, which is removed automatically when it is\n first hit. The arguments are the same as for "break".\n\ncl(ear) [filename:lineno | bpnumber [bpnumber ...]]\n\n With a *filename:lineno* argument, clear all the breakpoints at\n this line. With a space separated list of breakpoint numbers, clear\n those breakpoints. Without argument, clear all breaks (but first\n ask confirmation).\n\ndisable [bpnumber [bpnumber ...]]\n\n Disable the breakpoints given as a space separated list of\n breakpoint numbers. Disabling a breakpoint means it cannot cause\n the program to stop execution, but unlike clearing a breakpoint, it\n remains in the list of breakpoints and can be (re-)enabled.\n\nenable [bpnumber [bpnumber ...]]\n\n Enable the breakpoints specified.\n\nignore bpnumber [count]\n\n Set the ignore count for the given breakpoint number. If count is\n omitted, the ignore count is set to 0. A breakpoint becomes active\n when the ignore count is zero. When non-zero, the count is\n decremented each time the breakpoint is reached and the breakpoint\n is not disabled and any associated condition evaluates to true.\n\ncondition bpnumber [condition]\n\n Set a new *condition* for the breakpoint, an expression which must\n evaluate to true before the breakpoint is honored. If *condition*\n is absent, any existing condition is removed; i.e., the breakpoint\n is made unconditional.\n\ncommands [bpnumber]\n\n Specify a list of commands for breakpoint number *bpnumber*. The\n commands themselves appear on the following lines. Type a line\n containing just "end" to terminate the commands. An example:\n\n (Pdb) commands 1\n (com) print some_variable\n (com) end\n (Pdb)\n\n To remove all commands from a breakpoint, type commands and follow\n it immediately with "end"; that is, give no commands.\n\n With no *bpnumber* argument, commands refers to the last breakpoint\n set.\n\n You can use breakpoint commands to start your program up again.\n Simply use the continue command, or step, or any other command that\n resumes execution.\n\n Specifying any command resuming execution (currently continue,\n step, next, return, jump, quit and their abbreviations) terminates\n the command list (as if that command was immediately followed by\n end). This is because any time you resume execution (even with a\n simple next or step), you may encounter another breakpoint--which\n could have its own command list, leading to ambiguities about which\n list to execute.\n\n If you use the \'silent\' command in the command list, the usual\n message about stopping at a breakpoint is not printed. This may be\n desirable for breakpoints that are to print a specific message and\n then continue. If none of the other commands print anything, you\n see no sign that the breakpoint was reached.\n\ns(tep)\n\n Execute the current line, stop at the first possible occasion\n (either in a function that is called or on the next line in the\n current function).\n\nn(ext)\n\n Continue execution until the next line in the current function is\n reached or it returns. (The difference between "next" and "step"\n is that "step" stops inside a called function, while "next"\n executes called functions at (nearly) full speed, only stopping at\n the next line in the current function.)\n\nunt(il) [lineno]\n\n Without argument, continue execution until the line with a number\n greater than the current one is reached.\n\n With a line number, continue execution until a line with a number\n greater or equal to that is reached. In both cases, also stop when\n the current frame returns.\n\n Changed in version 3.2: Allow giving an explicit line number.\n\nr(eturn)\n\n Continue execution until the current function returns.\n\nc(ont(inue))\n\n Continue execution, only stop when a breakpoint is encountered.\n\nj(ump) lineno\n\n Set the next line that will be executed. Only available in the\n bottom-most frame. This lets you jump back and execute code again,\n or jump forward to skip code that you don\'t want to run.\n\n It should be noted that not all jumps are allowed -- for instance\n it is not possible to jump into the middle of a "for" loop or out\n of a "finally" clause.\n\nl(ist) [first[, last]]\n\n List source code for the current file. Without arguments, list 11\n lines around the current line or continue the previous listing.\n With "." as argument, list 11 lines around the current line. With\n one argument, list 11 lines around at that line. With two\n arguments, list the given range; if the second argument is less\n than the first, it is interpreted as a count.\n\n The current line in the current frame is indicated by "->". If an\n exception is being debugged, the line where the exception was\n originally raised or propagated is indicated by ">>", if it differs\n from the current line.\n\n New in version 3.2: The ">>" marker.\n\nll | longlist\n\n List all source code for the current function or frame.\n Interesting lines are marked as for "list".\n\n New in version 3.2.\n\na(rgs)\n\n Print the argument list of the current function.\n\np(rint) expression\n\n Evaluate the *expression* in the current context and print its\n value.\n\npp expression\n\n Like the "print" command, except the value of the expression is\n pretty-printed using the "pprint" module.\n\nwhatis expression\n\n Print the type of the *expression*.\n\nsource expression\n\n Try to get source code for the given object and display it.\n\n New in version 3.2.\n\ndisplay [expression]\n\n Display the value of the expression if it changed, each time\n execution stops in the current frame.\n\n Without expression, list all display expressions for the current\n frame.\n\n New in version 3.2.\n\nundisplay [expression]\n\n Do not display the expression any more in the current frame.\n Without expression, clear all display expressions for the current\n frame.\n\n New in version 3.2.\n\ninteract\n\n Start an interative interpreter (using the "code" module) whose\n global namespace contains all the (global and local) names found in\n the current scope.\n\n New in version 3.2.\n\nalias [name [command]]\n\n Create an alias called *name* that executes *command*. The command\n must *not* be enclosed in quotes. Replaceable parameters can be\n indicated by "%1", "%2", and so on, while "%*" is replaced by all\n the parameters. If no command is given, the current alias for\n *name* is shown. If no arguments are given, all aliases are listed.\n\n Aliases may be nested and can contain anything that can be legally\n typed at the pdb prompt. Note that internal pdb commands *can* be\n overridden by aliases. Such a command is then hidden until the\n alias is removed. Aliasing is recursively applied to the first\n word of the command line; all other words in the line are left\n alone.\n\n As an example, here are two useful aliases (especially when placed\n in the ".pdbrc" file):\n\n # Print instance variables (usage "pi classInst")\n alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k])\n # Print instance variables in self\n alias ps pi self\n\nunalias name\n\n Delete the specified alias.\n\n! statement\n\n Execute the (one-line) *statement* in the context of the current\n stack frame. The exclamation point can be omitted unless the first\n word of the statement resembles a debugger command. To set a\n global variable, you can prefix the assignment command with a\n "global" statement on the same line, e.g.:\n\n (Pdb) global list_options; list_options = [\'-l\']\n (Pdb)\n\nrun [args ...]\nrestart [args ...]\n\n Restart the debugged Python program. If an argument is supplied,\n it is split with "shlex" and the result is used as the new\n "sys.argv". History, breakpoints, actions and debugger options are\n preserved. "restart" is an alias for "run".\n\nq(uit)\n\n Quit from the debugger. The program being executed is aborted.\n\n-[ Footnotes ]-\n\n[1] Whether a frame is considered to originate in a certain module\n is determined by the "__name__" in the frame globals.\n', + 'del': '\nThe "del" statement\n*******************\n\n del_stmt ::= "del" target_list\n\nDeletion is recursively defined very similar to the way assignment is\ndefined. Rather than spelling it out in full details, here are some\nhints.\n\nDeletion of a target list recursively deletes each target, from left\nto right.\n\nDeletion of a name removes the binding of that name from the local or\nglobal namespace, depending on whether the name occurs in a "global"\nstatement in the same code block. If the name is unbound, a\n"NameError" exception will be raised.\n\nDeletion of attribute references, subscriptions and slicings is passed\nto the primary object involved; deletion of a slicing is in general\nequivalent to assignment of an empty slice of the right type (but even\nthis is determined by the sliced object).\n\nChanged in version 3.2: Previously it was illegal to delete a name\nfrom the local namespace if it occurs as a free variable in a nested\nblock.\n', 'dict': '\nDictionary displays\n*******************\n\nA dictionary display is a possibly empty series of key/datum pairs\nenclosed in curly braces:\n\n dict_display ::= "{" [key_datum_list | dict_comprehension] "}"\n key_datum_list ::= key_datum ("," key_datum)* [","]\n key_datum ::= expression ":" expression\n dict_comprehension ::= expression ":" expression comp_for\n\nA dictionary display yields a new dictionary object.\n\nIf a comma-separated sequence of key/datum pairs is given, they are\nevaluated from left to right to define the entries of the dictionary:\neach key object is used as a key into the dictionary to store the\ncorresponding datum. This means that you can specify the same key\nmultiple times in the key/datum list, and the final dictionary\'s value\nfor that key will be the last one given.\n\nA dict comprehension, in contrast to list and set comprehensions,\nneeds two expressions separated with a colon followed by the usual\n"for" and "if" clauses. When the comprehension is run, the resulting\nkey and value elements are inserted in the new dictionary in the order\nthey are produced.\n\nRestrictions on the types of the key values are listed earlier in\nsection *The standard type hierarchy*. (To summarize, the key type\nshould be *hashable*, which excludes all mutable objects.) Clashes\nbetween duplicate keys are not detected; the last datum (textually\nrightmost in the display) stored for a given key value prevails.\n', - 'dynamic-features': '\nInteraction with dynamic features\n*********************************\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- ``import *`` --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a ``SyntaxError``.\n\nThe ``eval()`` and ``exec()`` functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe ``exec()`` and ``eval()`` functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', - 'else': '\nThe ``if`` statement\n********************\n\nThe ``if`` statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the ``if`` statement is executed or evaluated).\nIf all expressions are false, the suite of the ``else`` clause, if\npresent, is executed.\n', - 'exceptions': '\nExceptions\n**********\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the ``raise`` statement. Exception\nhandlers are specified with the ``try`` ... ``except`` statement. The\n``finally`` clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n``SystemExit``.\n\nExceptions are identified by class instances. The ``except`` clause\nis selected depending on the class of the instance: it must reference\nthe class of the instance or a base class thereof. The instance can\nbe received by the handler and can carry additional information about\nthe exceptional condition.\n\nNote: Exception messages are not part of the Python API. Their contents\n may change from one version of Python to the next without warning\n and should not be relied on by code which will run under multiple\n versions of the interpreter.\n\nSee also the description of the ``try`` statement in section *The try\nstatement* and ``raise`` statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by these\n operations is not available at the time the module is compiled.\n', - 'execmodel': '\nExecution model\n***************\n\n\nNaming and binding\n==================\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions ``eval()`` and ``exec()`` is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as ``nonlocal``. If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a ``NameError`` exception is raised.\nIf the name refers to a local variable that has not been bound, a\n``UnboundLocalError`` exception is raised. ``UnboundLocalError`` is a\nsubclass of ``NameError``.\n\nThe following constructs bind names: formal parameters to functions,\n``import`` statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, ``for`` loop header, or\nafter ``as`` in a ``with`` statement or ``except`` clause. The\n``import`` statement of the form ``from ... import *`` binds all names\ndefined in the imported module, except those beginning with an\nunderscore. This form may only be used at the module level.\n\nA target occurring in a ``del`` statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the ``global`` statement occurs within a block, all uses of the\nname specified in the statement refer to the binding of that name in\nthe top-level namespace. Names are resolved in the top-level\nnamespace by searching the global namespace, i.e. the namespace of the\nmodule containing the code block, and the builtins namespace, the\nnamespace of the module ``builtins``. The global namespace is\nsearched first. If the name is not found there, the builtins\nnamespace is searched. The global statement must precede all uses of\nthe name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name ``__builtins__`` in its\nglobal namespace; this should be a dictionary or a module (in the\nlatter case the module\'s dictionary is used). By default, when in the\n``__main__`` module, ``__builtins__`` is the built-in module\n``builtins``; when in any other module, ``__builtins__`` is an alias\nfor the dictionary of the ``builtins`` module itself.\n``__builtins__`` can be set to a user-created dictionary to create a\nweak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n``__builtins__``; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should ``import``\nthe ``builtins`` module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n``__main__``.\n\nThe ``global`` statement has the same scope as a name binding\noperation in the same block. If the nearest enclosing scope for a\nfree variable contains a global statement, the free variable is\ntreated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n---------------------------------\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- ``import *`` --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a ``SyntaxError``.\n\nThe ``eval()`` and ``exec()`` functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe ``exec()`` and ``eval()`` functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the ``raise`` statement. Exception\nhandlers are specified with the ``try`` ... ``except`` statement. The\n``finally`` clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n``SystemExit``.\n\nExceptions are identified by class instances. The ``except`` clause\nis selected depending on the class of the instance: it must reference\nthe class of the instance or a base class thereof. The instance can\nbe received by the handler and can carry additional information about\nthe exceptional condition.\n\nNote: Exception messages are not part of the Python API. Their contents\n may change from one version of Python to the next without warning\n and should not be relied on by code which will run under multiple\n versions of the interpreter.\n\nSee also the description of the ``try`` statement in section *The try\nstatement* and ``raise`` statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by these\n operations is not available at the time the module is compiled.\n', - 'exprlists': '\nExpression lists\n****************\n\n expression_list ::= expression ( "," expression )* [","]\n\nAn expression list containing at least one comma yields a tuple. The\nlength of the tuple is the number of expressions in the list. The\nexpressions are evaluated from left to right.\n\nThe trailing comma is required only to create a single tuple (a.k.a. a\n*singleton*); it is optional in all other cases. A single expression\nwithout a trailing comma doesn\'t create a tuple, but rather yields the\nvalue of that expression. (To create an empty tuple, use an empty pair\nof parentheses: ``()``.)\n', - 'floating': '\nFloating point literals\n***********************\n\nFloating point literals are described by the following lexical\ndefinitions:\n\n floatnumber ::= pointfloat | exponentfloat\n pointfloat ::= [intpart] fraction | intpart "."\n exponentfloat ::= (intpart | pointfloat) exponent\n intpart ::= digit+\n fraction ::= "." digit+\n exponent ::= ("e" | "E") ["+" | "-"] digit+\n\nNote that the integer and exponent parts are always interpreted using\nradix 10. For example, ``077e010`` is legal, and denotes the same\nnumber as ``77e10``. The allowed range of floating point literals is\nimplementation-dependent. Some examples of floating point literals:\n\n 3.14 10. .001 1e100 3.14e-10 0e0\n\nNote that numeric literals do not include a sign; a phrase like ``-1``\nis actually an expression composed of the unary operator ``-`` and the\nliteral ``1``.\n', - 'for': '\nThe ``for`` statement\n*********************\n\nThe ``for`` statement is used to iterate over the elements of a\nsequence (such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n``expression_list``. The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a ``StopIteration``\nexception), the suite in the ``else`` clause, if present, is executed,\nand the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ncontinues with the next item, or with the ``else`` clause if there was\nno next item.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function ``range()`` returns an\niterator of integers suitable to emulate the effect of Pascal\'s ``for\ni := a to b do``; e.g., ``list(range(3))`` returns the list ``[0, 1,\n2]``.\n\nNote: There is a subtlety when the sequence is being modified by the loop\n (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n', - 'formatstrings': '\nFormat String Syntax\n********************\n\nThe ``str.format()`` method and the ``Formatter`` class share the same\nsyntax for format strings (although in the case of ``Formatter``,\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n``{}``. Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n``{{`` and ``}}``.\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= +\n conversion ::= "r" | "s" | "a"\n format_spec ::= \n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point ``\'!\'``, and a *format_spec*, which\nis preceded by a colon ``\':\'``. These specify a non-default format\nfor the replacement value.\n\nSee also the *Format Specification Mini-Language* section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings ``\'10\'`` or\n``\':-]\'``) within a format string. The *arg_name* can be followed by\nany number of index or attribute expressions. An expression of the\nform ``\'.name\'`` selects the named attribute using ``getattr()``,\nwhile an expression of the form ``\'[index]\'`` does an index lookup\nusing ``__getitem__()``.\n\nChanged in version 3.1: The positional argument specifiers can be\nomitted, so ``\'{} {}\'`` is equivalent to ``\'{0} {1}\'``.\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the\n``__format__()`` method of the value itself. However, in some cases\nit is desirable to force a type to be formatted as a string,\noverriding its own definition of formatting. By converting the value\nto a string before calling ``__format__()``, the normal formatting\nlogic is bypassed.\n\nThree conversion flags are currently supported: ``\'!s\'`` which calls\n``str()`` on the value, ``\'!r\'`` which calls ``repr()`` and ``\'!a\'``\nwhich calls ``ascii()``.\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n "More {!a}" # Calls ascii() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields can contain only a field\nname; conversion flags and format specifications are not allowed. The\nreplacement fields within the format_spec are substituted before the\n*format_spec* string is interpreted. This allows the formatting of a\nvalue to be dynamically specified.\n\nSee the *Format examples* section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see *Format String Syntax*). They can also be passed directly to the\nbuilt-in ``format()`` function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string (``""``) produces\nthe same result as if you had called ``str()`` on the value. A non-\nempty format string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= \n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nIf a valid *align* value is specified, it can be preceeded by a *fill*\ncharacter that can be any character and defaults to a space if\nomitted. Note that it is not possible to use ``{`` and ``}`` as *fill*\nchar while using the ``str.format()`` method; this limitation however\ndoesn\'t affect the ``format()`` function.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | ``\'<\'`` | Forces the field to be left-aligned within the available |\n | | space (this is the default for most objects). |\n +-----------+------------------------------------------------------------+\n | ``\'>\'`` | Forces the field to be right-aligned within the available |\n | | space (this is the default for numbers). |\n +-----------+------------------------------------------------------------+\n | ``\'=\'`` | Forces the padding to be placed after the sign (if any) |\n | | but before the digits. This is used for printing fields |\n | | in the form \'+000000120\'. This alignment option is only |\n | | valid for numeric types. |\n +-----------+------------------------------------------------------------+\n | ``\'^\'`` | Forces the field to be centered within the available |\n | | space. |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | ``\'+\'`` | indicates that a sign should be used for both positive as |\n | | well as negative numbers. |\n +-----------+------------------------------------------------------------+\n | ``\'-\'`` | indicates that a sign should be used only for negative |\n | | numbers (this is the default behavior). |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n | | numbers, and a minus sign on negative numbers. |\n +-----------+------------------------------------------------------------+\n\nThe ``\'#\'`` option causes the "alternate form" to be used for the\nconversion. The alternate form is defined differently for different\ntypes. This option is only valid for integer, float, complex and\nDecimal types. For integers, when binary, octal, or hexadecimal output\nis used, this option adds the prefix respective ``\'0b\'``, ``\'0o\'``, or\n``\'0x\'`` to the output value. For floats, complex and Decimal the\nalternate form causes the result of the conversion to always contain a\ndecimal-point character, even if no digits follow it. Normally, a\ndecimal-point character appears in the result of these conversions\nonly if a digit follows it. In addition, for ``\'g\'`` and ``\'G\'``\nconversions, trailing zeros are not removed from the result.\n\nThe ``\',\'`` option signals the use of a comma for a thousands\nseparator. For a locale aware separator, use the ``\'n\'`` integer\npresentation type instead.\n\nChanged in version 3.1: Added the ``\',\'`` option (see also **PEP\n378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nPreceding the *width* field by a zero (``\'0\'``) character enables\nsign-aware zero-padding for numeric types. This is equivalent to a\n*fill* character of ``\'0\'`` with an *alignment* type of ``\'=\'``.\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with ``\'f\'`` and ``\'F\'``, or before and after the decimal\npoint for a floating point value formatted with ``\'g\'`` or ``\'G\'``.\nFor non-number types the field indicates the maximum field size - in\nother words, how many characters will be used from the field content.\nThe *precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'s\'`` | String format. This is the default type for strings and |\n | | may be omitted. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'s\'``. |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'b\'`` | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | ``\'c\'`` | Character. Converts the integer to the corresponding |\n | | unicode character before printing. |\n +-----------+------------------------------------------------------------+\n | ``\'d\'`` | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | ``\'o\'`` | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | ``\'x\'`` | Hex format. Outputs the number in base 16, using lower- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | ``\'X\'`` | Hex format. Outputs the number in base 16, using upper- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | ``\'n\'`` | Number. This is the same as ``\'d\'``, except that it uses |\n | | the current locale setting to insert the appropriate |\n | | number separator characters. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'d\'``. |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except\n``\'n\'`` and None). When doing so, ``float()`` is used to convert the\ninteger to a floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'e\'`` | Exponent notation. Prints the number in scientific |\n | | notation using the letter \'e\' to indicate the exponent. |\n | | The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'E\'`` | Exponent notation. Same as ``\'e\'`` except it uses an upper |\n | | case \'E\' as the separator character. |\n +-----------+------------------------------------------------------------+\n | ``\'f\'`` | Fixed point. Displays the number as a fixed-point number. |\n | | The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'F\'`` | Fixed point. Same as ``\'f\'``, but converts ``nan`` to |\n | | ``NAN`` and ``inf`` to ``INF``. |\n +-----------+------------------------------------------------------------+\n | ``\'g\'`` | General format. For a given precision ``p >= 1``, this |\n | | rounds the number to ``p`` significant digits and then |\n | | formats the result in either fixed-point format or in |\n | | scientific notation, depending on its magnitude. The |\n | | precise rules are as follows: suppose that the result |\n | | formatted with presentation type ``\'e\'`` and precision |\n | | ``p-1`` would have exponent ``exp``. Then if ``-4 <= exp |\n | | < p``, the number is formatted with presentation type |\n | | ``\'f\'`` and precision ``p-1-exp``. Otherwise, the number |\n | | is formatted with presentation type ``\'e\'`` and precision |\n | | ``p-1``. In both cases insignificant trailing zeros are |\n | | removed from the significand, and the decimal point is |\n | | also removed if there are no remaining digits following |\n | | it. Positive and negative infinity, positive and negative |\n | | zero, and nans, are formatted as ``inf``, ``-inf``, ``0``, |\n | | ``-0`` and ``nan`` respectively, regardless of the |\n | | precision. A precision of ``0`` is treated as equivalent |\n | | to a precision of ``1``. The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'G\'`` | General format. Same as ``\'g\'`` except switches to ``\'E\'`` |\n | | if the number gets too large. The representations of |\n | | infinity and NaN are uppercased, too. |\n +-----------+------------------------------------------------------------+\n | ``\'n\'`` | Number. This is the same as ``\'g\'``, except that it uses |\n | | the current locale setting to insert the appropriate |\n | | number separator characters. |\n +-----------+------------------------------------------------------------+\n | ``\'%\'`` | Percentage. Multiplies the number by 100 and displays in |\n | | fixed (``\'f\'``) format, followed by a percent sign. |\n +-----------+------------------------------------------------------------+\n | None | Similar to ``\'g\'``, except with at least one digit past |\n | | the decimal point and a default precision of 12. This is |\n | | intended to match ``str()``, except you can add the other |\n | | format modifiers. |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the new format syntax and comparison\nwith the old ``%``-formatting.\n\nIn most of the cases the syntax is similar to the old\n``%``-formatting, with the addition of the ``{}`` and with ``:`` used\ninstead of ``%``. For example, ``\'%03.2f\'`` can be translated to\n``\'{:03.2f}\'``.\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 3.1+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point:\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing ``%s`` and ``%r``:\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing ``%x`` and ``%o`` and converting the value to different\nbases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 86.36%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12): #doctest: +NORMALIZE_WHITESPACE\n ... for base in \'dXob\':\n ... print(\'{0:{width}{base}}\'.format(num, base=base, width=width), end=\' \')\n ... print()\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n', - 'function': '\nFunction definitions\n********************\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* ``=``\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the "``*``" must also have a default value ---\nthis is a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use ``None`` as the\ndefault, and explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n"``*identifier``" is present, it is initialized to a tuple receiving\nany excess positional parameters, defaulting to the empty tuple. If\nthe form "``**identifier``" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after "``*``" or "``*identifier``" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "``: expression``"\nfollowing the parameter name. Any parameter may have an annotation\neven those of the form ``*identifier`` or ``**identifier``. Functions\nmay have "return" annotation of the form "``-> expression``" after the\nparameter list. These annotations can be any valid Python expression\nand are evaluated when the function definition is executed.\nAnnotations may be evaluated in a different order than they appear in\nthe source code. The presence of annotations does not change the\nsemantics of a function. The annotation values are available as\nvalues of a dictionary keyed by the parameters\' names in the\n``__annotations__`` attribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a "``def``" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The "``def``" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A "``def``"\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also:\n\n **PEP 3107** - Function Annotations\n The original specification for function annotations.\n', - 'global': '\nThe ``global`` statement\n************************\n\n global_stmt ::= "global" identifier ("," identifier)*\n\nThe ``global`` statement is a declaration which holds for the entire\ncurrent code block. It means that the listed identifiers are to be\ninterpreted as globals. It would be impossible to assign to a global\nvariable without ``global``, although free variables may refer to\nglobals without being declared global.\n\nNames listed in a ``global`` statement must not be used in the same\ncode block textually preceding that ``global`` statement.\n\nNames listed in a ``global`` statement must not be defined as formal\nparameters or in a ``for`` loop control target, ``class`` definition,\nfunction definition, or ``import`` statement.\n\n**CPython implementation detail:** The current implementation does not\nenforce the latter two restrictions, but programs should not abuse\nthis freedom, as future implementations may enforce them or silently\nchange the meaning of the program.\n\n**Programmer\'s note:** the ``global`` is a directive to the parser.\nIt applies only to code parsed at the same time as the ``global``\nstatement. In particular, a ``global`` statement contained in a string\nor code object supplied to the built-in ``exec()`` function does not\naffect the code block *containing* the function call, and code\ncontained in such a string is unaffected by ``global`` statements in\nthe code containing the function call. The same applies to the\n``eval()`` and ``compile()`` functions.\n', - 'id-classes': '\nReserved classes of identifiers\n*******************************\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n``_*``\n Not imported by ``from module import *``. The special identifier\n ``_`` is used in the interactive interpreter to store the result of\n the last evaluation; it is stored in the ``builtins`` module. When\n not in interactive mode, ``_`` has no special meaning and is not\n defined. See section *The import statement*.\n\n Note: The name ``_`` is often used in conjunction with\n internationalization; refer to the documentation for the\n ``gettext`` module for more information on this convention.\n\n``__*__``\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of ``__*__`` names, in any context, that does\n not follow explicitly documented use, is subject to breakage\n without warning.\n\n``__*``\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', - 'identifiers': '\nIdentifiers and keywords\n************************\n\nIdentifiers (also referred to as *names*) are described by the\nfollowing lexical definitions.\n\nThe syntax of identifiers in Python is based on the Unicode standard\nannex UAX-31, with elaboration and changes as defined below; see also\n**PEP 3131** for further details.\n\nWithin the ASCII range (U+0001..U+007F), the valid characters for\nidentifiers are the same as in Python 2.x: the uppercase and lowercase\nletters ``A`` through ``Z``, the underscore ``_`` and, except for the\nfirst character, the digits ``0`` through ``9``.\n\nPython 3.0 introduces additional characters from outside the ASCII\nrange (see **PEP 3131**). For these characters, the classification\nuses the version of the Unicode Character Database as included in the\n``unicodedata`` module.\n\nIdentifiers are unlimited in length. Case is significant.\n\n identifier ::= xid_start xid_continue*\n id_start ::= \n id_continue ::= \n xid_start ::= \n xid_continue ::= \n\nThe Unicode category codes mentioned above stand for:\n\n* *Lu* - uppercase letters\n\n* *Ll* - lowercase letters\n\n* *Lt* - titlecase letters\n\n* *Lm* - modifier letters\n\n* *Lo* - other letters\n\n* *Nl* - letter numbers\n\n* *Mn* - nonspacing marks\n\n* *Mc* - spacing combining marks\n\n* *Nd* - decimal numbers\n\n* *Pc* - connector punctuations\n\n* *Other_ID_Start* - explicit list of characters in PropList.txt to\n support backwards compatibility\n\n* *Other_ID_Continue* - likewise\n\nAll identifiers are converted into the normal form NFKC while parsing;\ncomparison of identifiers is based on NFKC.\n\nA non-normative HTML file listing all valid identifier characters for\nUnicode 4.1 can be found at http://www.dcl.hpi.uni-\npotsdam.de/home/loewis/table-3131.html.\n\n\nKeywords\n========\n\nThe following identifiers are used as reserved words, or *keywords* of\nthe language, and cannot be used as ordinary identifiers. They must\nbe spelled exactly as written here:\n\n False class finally is return\n None continue for lambda try\n True def from nonlocal while\n and del global not with\n as elif if or yield\n assert else import pass\n break except in raise\n\n\nReserved classes of identifiers\n===============================\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n``_*``\n Not imported by ``from module import *``. The special identifier\n ``_`` is used in the interactive interpreter to store the result of\n the last evaluation; it is stored in the ``builtins`` module. When\n not in interactive mode, ``_`` has no special meaning and is not\n defined. See section *The import statement*.\n\n Note: The name ``_`` is often used in conjunction with\n internationalization; refer to the documentation for the\n ``gettext`` module for more information on this convention.\n\n``__*__``\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of ``__*__`` names, in any context, that does\n not follow explicitly documented use, is subject to breakage\n without warning.\n\n``__*``\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', - 'if': '\nThe ``if`` statement\n********************\n\nThe ``if`` statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the ``if`` statement is executed or evaluated).\nIf all expressions are false, the suite of the ``else`` clause, if\npresent, is executed.\n', - 'imaginary': '\nImaginary literals\n******************\n\nImaginary literals are described by the following lexical definitions:\n\n imagnumber ::= (floatnumber | intpart) ("j" | "J")\n\nAn imaginary literal yields a complex number with a real part of 0.0.\nComplex numbers are represented as a pair of floating point numbers\nand have the same restrictions on their range. To create a complex\nnumber with a nonzero real part, add a floating point number to it,\ne.g., ``(3+4j)``. Some examples of imaginary literals:\n\n 3.14j 10.j 10j .001j 1e100j 3.14e-10j\n', - 'import': '\nThe ``import`` statement\n************************\n\n import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*\n | "from" relative_module "import" identifier ["as" name]\n ( "," identifier ["as" name] )*\n | "from" relative_module "import" "(" identifier ["as" name]\n ( "," identifier ["as" name] )* [","] ")"\n | "from" module "import" "*"\n module ::= (identifier ".")* identifier\n relative_module ::= "."* module | "."+\n name ::= identifier\n\nThe basic import statement (no ``from`` clause) is executed in two\nsteps:\n\n1. find a module, loading and initializing it if necessary\n\n2. define a name or names in the local namespace for the scope where\n the ``import`` statement occurs.\n\nWhen the statement contains multiple clauses (separated by commas) the\ntwo steps are carried out separately for each clause, just as though\nthe clauses had been separated out into individiual import statements.\n\nThe details of the first step, finding and loading modules is\ndescribed in greater detail in the section on the *import system*,\nwhich also describes the various types of packages and modules that\ncan be imported, as well as all the hooks that can be used to\ncustomize the import system. Note that failures in this step may\nindicate either that the module could not be located, *or* that an\nerror occurred while initializing the module, which includes execution\nof the module\'s code.\n\nIf the requested module is retrieved successfully, it will be made\navailable in the local namespace in one of three ways:\n\n* If the module name is followed by ``as``, then the name following\n ``as`` is bound directly to the imported module.\n\n* If no other name is specified, and the module being imported is a\n top level module, the module\'s name is bound in the local namespace\n as a reference to the imported module\n\n* If the module being imported is *not* a top level module, then the\n name of the top level package that contains the module is bound in\n the local namespace as a reference to the top level package. The\n imported module must be accessed using its full qualified name\n rather than directly\n\nThe ``from`` form uses a slightly more complex process:\n\n1. find the module specified in the ``from`` clause loading and\n initializing it if necessary;\n\n2. for each of the identifiers specified in the ``import`` clauses:\n\n 1. check if the imported module has an attribute by that name\n\n 2. if not, attempt to import a submodule with that name and then\n check the imported module again for that attribute\n\n 3. if the attribute is not found, ``ImportError`` is raised.\n\n 4. otherwise, a reference to that value is bound in the local\n namespace, using the name in the ``as`` clause if it is present,\n otherwise using the attribute name\n\nExamples:\n\n import foo # foo imported and bound locally\n import foo.bar.baz # foo.bar.baz imported, foo bound locally\n import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb\n from foo.bar import baz # foo.bar.baz imported and bound as baz\n from foo import attr # foo imported and foo.attr bound as attr\n\nIf the list of identifiers is replaced by a star (``\'*\'``), all public\nnames defined in the module are bound in the local namespace for the\nscope where the ``import`` statement occurs.\n\nThe *public names* defined by a module are determined by checking the\nmodule\'s namespace for a variable named ``__all__``; if defined, it\nmust be a sequence of strings which are names defined or imported by\nthat module. The names given in ``__all__`` are all considered public\nand are required to exist. If ``__all__`` is not defined, the set of\npublic names includes all names found in the module\'s namespace which\ndo not begin with an underscore character (``\'_\'``). ``__all__``\nshould contain the entire public API. It is intended to avoid\naccidentally exporting items that are not part of the API (such as\nlibrary modules which were imported and used within the module).\n\nThe ``from`` form with ``*`` may only occur in a module scope. The\nwild card form of import --- ``import *`` --- is only allowed at the\nmodule level. Attempting to use it in class or function definitions\nwill raise a ``SyntaxError``.\n\nWhen specifying what module to import you do not have to specify the\nabsolute name of the module. When a module or package is contained\nwithin another package it is possible to make a relative import within\nthe same top package without having to mention the package name. By\nusing leading dots in the specified module or package after ``from``\nyou can specify how high to traverse up the current package hierarchy\nwithout specifying exact names. One leading dot means the current\npackage where the module making the import exists. Two dots means up\none package level. Three dots is up two levels, etc. So if you execute\n``from . import mod`` from a module in the ``pkg`` package then you\nwill end up importing ``pkg.mod``. If you execute ``from ..subpkg2\nimport mod`` from within ``pkg.subpkg1`` you will import\n``pkg.subpkg2.mod``. The specification for relative imports is\ncontained within **PEP 328**.\n\n``importlib.import_module()`` is provided to support applications that\ndetermine which modules need to be loaded dynamically.\n\n\nFuture statements\n=================\n\nA *future statement* is a directive to the compiler that a particular\nmodule should be compiled using syntax or semantics that will be\navailable in a specified future release of Python. The future\nstatement is intended to ease migration to future versions of Python\nthat introduce incompatible changes to the language. It allows use of\nthe new features on a per-module basis before the release in which the\nfeature becomes standard.\n\n future_statement ::= "from" "__future__" "import" feature ["as" name]\n ("," feature ["as" name])*\n | "from" "__future__" "import" "(" feature ["as" name]\n ("," feature ["as" name])* [","] ")"\n feature ::= identifier\n name ::= identifier\n\nA future statement must appear near the top of the module. The only\nlines that can appear before a future statement are:\n\n* the module docstring (if any),\n\n* comments,\n\n* blank lines, and\n\n* other future statements.\n\nThe features recognized by Python 3.0 are ``absolute_import``,\n``division``, ``generators``, ``unicode_literals``,\n``print_function``, ``nested_scopes`` and ``with_statement``. They\nare all redundant because they are always enabled, and only kept for\nbackwards compatibility.\n\nA future statement is recognized and treated specially at compile\ntime: Changes to the semantics of core constructs are often\nimplemented by generating different code. It may even be the case\nthat a new feature introduces new incompatible syntax (such as a new\nreserved word), in which case the compiler may need to parse the\nmodule differently. Such decisions cannot be pushed off until\nruntime.\n\nFor any given release, the compiler knows which feature names have\nbeen defined, and raises a compile-time error if a future statement\ncontains a feature not known to it.\n\nThe direct runtime semantics are the same as for any import statement:\nthere is a standard module ``__future__``, described later, and it\nwill be imported in the usual way at the time the future statement is\nexecuted.\n\nThe interesting runtime semantics depend on the specific feature\nenabled by the future statement.\n\nNote that there is nothing special about the statement:\n\n import __future__ [as name]\n\nThat is not a future statement; it\'s an ordinary import statement with\nno special semantics or syntax restrictions.\n\nCode compiled by calls to the built-in functions ``exec()`` and\n``compile()`` that occur in a module ``M`` containing a future\nstatement will, by default, use the new syntax or semantics associated\nwith the future statement. This can be controlled by optional\narguments to ``compile()`` --- see the documentation of that function\nfor details.\n\nA future statement typed at an interactive interpreter prompt will\ntake effect for the rest of the interpreter session. If an\ninterpreter is started with the *-i* option, is passed a script name\nto execute, and the script includes a future statement, it will be in\neffect in the interactive session started after the script is\nexecuted.\n\nSee also:\n\n **PEP 236** - Back to the __future__\n The original proposal for the __future__ mechanism.\n', - 'in': '\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like ``a < b < c`` have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: ``True`` or ``False``.\n\nComparisons can be chained arbitrarily, e.g., ``x < y <= z`` is\nequivalent to ``x < y and y <= z``, except that ``y`` is evaluated\nonly once (but in both cases ``z`` is not evaluated at all when ``x <\ny`` is found to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then ``a op1 b op2 c ... y\nopN z`` is equivalent to ``a op1 b and b op2 c and ... y opN z``,\nexcept that each expression is evaluated at most once.\n\nNote that ``a op1 b op2 c`` doesn\'t imply any kind of comparison\nbetween *a* and *c*, so that, e.g., ``x < y > z`` is perfectly legal\n(though perhaps not pretty).\n\nThe operators ``<``, ``>``, ``==``, ``>=``, ``<=``, and ``!=`` compare\nthe values of two objects. The objects need not have the same type.\nIf both are numbers, they are converted to a common type. Otherwise,\nthe ``==`` and ``!=`` operators *always* consider objects of different\ntypes to be unequal, while the ``<``, ``>``, ``>=`` and ``<=``\noperators raise a ``TypeError`` when comparing objects of different\ntypes that do not implement these operators for the given pair of\ntypes. You can control comparison behavior of objects of non-built-in\ntypes by defining rich comparison methods like ``__gt__()``, described\nin section *Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values ``float(\'NaN\')`` and ``Decimal(\'NaN\')`` are special. The\n are identical to themselves, ``x is x`` but are not equal to\n themselves, ``x != x``. Additionally, comparing any value to a\n not-a-number value will return ``False``. For example, both ``3 <\n float(\'NaN\')`` and ``float(\'NaN\') < 3`` will return ``False``.\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric equivalents\n (the result of the built-in function ``ord()``) of their characters.\n [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison of\n corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, ``[1,2,x] <= [1,2,y]`` has the\n same value as ``x <= y``. If the corresponding element does not\n exist, the shorter sequence is ordered first (for example, ``[1,2] <\n [1,2,3]``).\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same ``(key, value)`` pairs. Order comparisons ``(\'<\', \'<=\', \'>=\',\n \'>\')`` raise ``TypeError``.\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets ``{1,2}`` and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, ``min()``, ``max()``, and ``sorted()`` produce\n undefined results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they are\n the same object; the choice whether one object is considered smaller\n or larger than another one is made arbitrarily but consistently\n within one execution of a program.\n\nComparison of objects of the differing types depends on whether either\nof the types provide explicit support for the comparison. Most\nnumeric types can be compared with one another. When cross-type\ncomparison is not supported, the comparison method returns\n``NotImplemented``.\n\nThe operators ``in`` and ``not in`` test for membership. ``x in s``\nevaluates to true if *x* is a member of *s*, and false otherwise. ``x\nnot in s`` returns the negation of ``x in s``. All built-in sequences\nand set types support this as well as dictionary, for which ``in``\ntests whether a the dictionary has a given key. For container types\nsuch as list, tuple, set, frozenset, dict, or collections.deque, the\nexpression ``x in y`` is equivalent to ``any(x is e or x == e for e in\ny)``.\n\nFor the string and bytes types, ``x in y`` is true if and only if *x*\nis a substring of *y*. An equivalent test is ``y.find(x) != -1``.\nEmpty strings are always considered to be a substring of any other\nstring, so ``"" in "abc"`` will return ``True``.\n\nFor user-defined classes which define the ``__contains__()`` method,\n``x in y`` is true if and only if ``y.__contains__(x)`` is true.\n\nFor user-defined classes which do not define ``__contains__()`` but do\ndefine ``__iter__()``, ``x in y`` is true if some value ``z`` with ``x\n== z`` is produced while iterating over ``y``. If an exception is\nraised during the iteration, it is as if ``in`` raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n``__getitem__()``, ``x in y`` is true if and only if there is a non-\nnegative integer index *i* such that ``x == y[i]``, and all lower\ninteger indices do not raise ``IndexError`` exception. (If any other\nexception is raised, it is as if ``in`` raised that exception).\n\nThe operator ``not in`` is defined to have the inverse true value of\n``in``.\n\nThe operators ``is`` and ``is not`` test for object identity: ``x is\ny`` is true if and only if *x* and *y* are the same object. ``x is\nnot y`` yields the inverse truth value. [4]\n', + 'dynamic-features': '\nInteraction with dynamic features\n*********************************\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', + 'else': '\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', + 'exceptions': '\nExceptions\n**********\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', + 'execmodel': '\nExecution model\n***************\n\n\nNaming and binding\n==================\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal". If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, a\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\nglobal statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n---------------------------------\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', + 'exprlists': '\nExpression lists\n****************\n\n expression_list ::= expression ( "," expression )* [","]\n\nAn expression list containing at least one comma yields a tuple. The\nlength of the tuple is the number of expressions in the list. The\nexpressions are evaluated from left to right.\n\nThe trailing comma is required only to create a single tuple (a.k.a. a\n*singleton*); it is optional in all other cases. A single expression\nwithout a trailing comma doesn\'t create a tuple, but rather yields the\nvalue of that expression. (To create an empty tuple, use an empty pair\nof parentheses: "()".)\n', + 'floating': '\nFloating point literals\n***********************\n\nFloating point literals are described by the following lexical\ndefinitions:\n\n floatnumber ::= pointfloat | exponentfloat\n pointfloat ::= [intpart] fraction | intpart "."\n exponentfloat ::= (intpart | pointfloat) exponent\n intpart ::= digit+\n fraction ::= "." digit+\n exponent ::= ("e" | "E") ["+" | "-"] digit+\n\nNote that the integer and exponent parts are always interpreted using\nradix 10. For example, "077e010" is legal, and denotes the same number\nas "77e10". The allowed range of floating point literals is\nimplementation-dependent. Some examples of floating point literals:\n\n 3.14 10. .001 1e100 3.14e-10 0e0\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator "-" and the\nliteral "1".\n', + 'for': '\nThe "for" statement\n*******************\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there was no next\nitem.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n', + 'formatstrings': '\nFormat String Syntax\n********************\n\nThe "str.format()" method and the "Formatter" class share the same\nsyntax for format strings (although in the case of "Formatter",\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n"{}". Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n"{{" and "}}".\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= +\n conversion ::= "r" | "s" | "a"\n format_spec ::= \n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point "\'!\'", and a *format_spec*, which is\npreceded by a colon "\':\'". These specify a non-default format for the\nreplacement value.\n\nSee also the *Format Specification Mini-Language* section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings "\'10\'" or\n"\':-]\'") within a format string. The *arg_name* can be followed by any\nnumber of index or attribute expressions. An expression of the form\n"\'.name\'" selects the named attribute using "getattr()", while an\nexpression of the form "\'[index]\'" does an index lookup using\n"__getitem__()".\n\nChanged in version 3.1: The positional argument specifiers can be\nomitted, so "\'{} {}\'" is equivalent to "\'{0} {1}\'".\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the "__format__()"\nmethod of the value itself. However, in some cases it is desirable to\nforce a type to be formatted as a string, overriding its own\ndefinition of formatting. By converting the value to a string before\ncalling "__format__()", the normal formatting logic is bypassed.\n\nThree conversion flags are currently supported: "\'!s\'" which calls\n"str()" on the value, "\'!r\'" which calls "repr()" and "\'!a\'" which\ncalls "ascii()".\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n "More {!a}" # Calls ascii() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields can contain only a field\nname; conversion flags and format specifications are not allowed. The\nreplacement fields within the format_spec are substituted before the\n*format_spec* string is interpreted. This allows the formatting of a\nvalue to be dynamically specified.\n\nSee the *Format examples* section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see *Format String Syntax*). They can also be passed directly to the\nbuilt-in "format()" function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string ("""") produces\nthe same result as if you had called "str()" on the value. A non-empty\nformat string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= \n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nIf a valid *align* value is specified, it can be preceded by a *fill*\ncharacter that can be any character and defaults to a space if\nomitted. Note that it is not possible to use "{" and "}" as *fill*\nchar while using the "str.format()" method; this limitation however\ndoesn\'t affect the "format()" function.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'<\'" | Forces the field to be left-aligned within the available |\n +-----------+------------------------------------------------------------+\n | "\'>\'" | Forces the field to be right-aligned within the available |\n +-----------+------------------------------------------------------------+\n | "\'=\'" | Forces the padding to be placed after the sign (if any) |\n +-----------+------------------------------------------------------------+\n | "\'^\'" | Forces the field to be centered within the available |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'+\'" | indicates that a sign should be used for both positive as |\n +-----------+------------------------------------------------------------+\n | "\'-\'" | indicates that a sign should be used only for negative |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n +-----------+------------------------------------------------------------+\n\nThe "\'#\'" option causes the "alternate form" to be used for the\nconversion. The alternate form is defined differently for different\ntypes. This option is only valid for integer, float, complex and\nDecimal types. For integers, when binary, octal, or hexadecimal output\nis used, this option adds the prefix respective "\'0b\'", "\'0o\'", or\n"\'0x\'" to the output value. For floats, complex and Decimal the\nalternate form causes the result of the conversion to always contain a\ndecimal-point character, even if no digits follow it. Normally, a\ndecimal-point character appears in the result of these conversions\nonly if a digit follows it. In addition, for "\'g\'" and "\'G\'"\nconversions, trailing zeros are not removed from the result.\n\nThe "\',\'" option signals the use of a comma for a thousands separator.\nFor a locale aware separator, use the "\'n\'" integer presentation type\ninstead.\n\nChanged in version 3.1: Added the "\',\'" option (see also **PEP 378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nPreceding the *width* field by a zero ("\'0\'") character enables sign-\naware zero-padding for numeric types. This is equivalent to a *fill*\ncharacter of "\'0\'" with an *alignment* type of "\'=\'".\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with "\'f\'" and "\'F\'", or before and after the decimal point\nfor a floating point value formatted with "\'g\'" or "\'G\'". For non-\nnumber types the field indicates the maximum field size - in other\nwords, how many characters will be used from the field content. The\n*precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'s\'" | String format. This is the default type for strings and |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'s\'". |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'b\'" | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | "\'c\'" | Character. Converts the integer to the corresponding |\n +-----------+------------------------------------------------------------+\n | "\'d\'" | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | "\'o\'" | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | "\'x\'" | Hex format. Outputs the number in base 16, using lower- |\n +-----------+------------------------------------------------------------+\n | "\'X\'" | Hex format. Outputs the number in base 16, using upper- |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'d\'", except that it uses the |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'d\'". |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except "\'n\'"\nand None). When doing so, "float()" is used to convert the integer to\na floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'e\'" | Exponent notation. Prints the number in scientific |\n +-----------+------------------------------------------------------------+\n | "\'E\'" | Exponent notation. Same as "\'e\'" except it uses an upper |\n +-----------+------------------------------------------------------------+\n | "\'f\'" | Fixed point. Displays the number as a fixed-point number. |\n +-----------+------------------------------------------------------------+\n | "\'F\'" | Fixed point. Same as "\'f\'", but converts "nan" to "NAN" |\n +-----------+------------------------------------------------------------+\n | "\'g\'" | General format. For a given precision "p >= 1", this |\n +-----------+------------------------------------------------------------+\n | "\'G\'" | General format. Same as "\'g\'" except switches to "\'E\'" if |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'g\'", except that it uses the |\n +-----------+------------------------------------------------------------+\n | "\'%\'" | Percentage. Multiplies the number by 100 and displays in |\n +-----------+------------------------------------------------------------+\n | None | Similar to "\'g\'", except with at least one digit past the |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the new format syntax and comparison\nwith the old "%"-formatting.\n\nIn most of the cases the syntax is similar to the old "%"-formatting,\nwith the addition of the "{}" and with ":" used instead of "%". For\nexample, "\'%03.2f\'" can be translated to "\'{:03.2f}\'".\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 3.1+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point:\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing "%s" and "%r":\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing "%+f", "%-f", and "% f" and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing "%x" and "%o" and converting the value to different bases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 86.36%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12): #doctest: +NORMALIZE_WHITESPACE\n ... for base in \'dXob\':\n ... print(\'{0:{width}{base}}\'.format(num, base=base, width=width), end=\' \')\n ... print()\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n', + 'function': '\nFunction definitions\n********************\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use "None" as the default,\nand explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n', + 'global': '\nThe "global" statement\n**********************\n\n global_stmt ::= "global" identifier ("," identifier)*\n\nThe "global" statement is a declaration which holds for the entire\ncurrent code block. It means that the listed identifiers are to be\ninterpreted as globals. It would be impossible to assign to a global\nvariable without "global", although free variables may refer to\nglobals without being declared global.\n\nNames listed in a "global" statement must not be used in the same code\nblock textually preceding that "global" statement.\n\nNames listed in a "global" statement must not be defined as formal\nparameters or in a "for" loop control target, "class" definition,\nfunction definition, or "import" statement.\n\n**CPython implementation detail:** The current implementation does not\nenforce the latter two restrictions, but programs should not abuse\nthis freedom, as future implementations may enforce them or silently\nchange the meaning of the program.\n\n**Programmer\'s note:** the "global" is a directive to the parser. It\napplies only to code parsed at the same time as the "global"\nstatement. In particular, a "global" statement contained in a string\nor code object supplied to the built-in "exec()" function does not\naffect the code block *containing* the function call, and code\ncontained in such a string is unaffected by "global" statements in the\ncode containing the function call. The same applies to the "eval()"\nand "compile()" functions.\n', + 'id-classes': '\nReserved classes of identifiers\n*******************************\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "builtins" module. When not\n in interactive mode, "_" has no special meaning and is not defined.\n See section *The import statement*.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', + 'identifiers': '\nIdentifiers and keywords\n************************\n\nIdentifiers (also referred to as *names*) are described by the\nfollowing lexical definitions.\n\nThe syntax of identifiers in Python is based on the Unicode standard\nannex UAX-31, with elaboration and changes as defined below; see also\n**PEP 3131** for further details.\n\nWithin the ASCII range (U+0001..U+007F), the valid characters for\nidentifiers are the same as in Python 2.x: the uppercase and lowercase\nletters "A" through "Z", the underscore "_" and, except for the first\ncharacter, the digits "0" through "9".\n\nPython 3.0 introduces additional characters from outside the ASCII\nrange (see **PEP 3131**). For these characters, the classification\nuses the version of the Unicode Character Database as included in the\n"unicodedata" module.\n\nIdentifiers are unlimited in length. Case is significant.\n\n identifier ::= xid_start xid_continue*\n id_start ::= \n id_continue ::= \n xid_start ::= \n xid_continue ::= \n\nThe Unicode category codes mentioned above stand for:\n\n* *Lu* - uppercase letters\n\n* *Ll* - lowercase letters\n\n* *Lt* - titlecase letters\n\n* *Lm* - modifier letters\n\n* *Lo* - other letters\n\n* *Nl* - letter numbers\n\n* *Mn* - nonspacing marks\n\n* *Mc* - spacing combining marks\n\n* *Nd* - decimal numbers\n\n* *Pc* - connector punctuations\n\n* *Other_ID_Start* - explicit list of characters in PropList.txt to\n support backwards compatibility\n\n* *Other_ID_Continue* - likewise\n\nAll identifiers are converted into the normal form NFKC while parsing;\ncomparison of identifiers is based on NFKC.\n\nA non-normative HTML file listing all valid identifier characters for\nUnicode 4.1 can be found at http://www.dcl.hpi.uni-\npotsdam.de/home/loewis/table-3131.html.\n\n\nKeywords\n========\n\nThe following identifiers are used as reserved words, or *keywords* of\nthe language, and cannot be used as ordinary identifiers. They must\nbe spelled exactly as written here:\n\n False class finally is return\n None continue for lambda try\n True def from nonlocal while\n and del global not with\n as elif if or yield\n assert else import pass\n break except in raise\n\n\nReserved classes of identifiers\n===============================\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "builtins" module. When not\n in interactive mode, "_" has no special meaning and is not defined.\n See section *The import statement*.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', + 'if': '\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', + 'imaginary': '\nImaginary literals\n******************\n\nImaginary literals are described by the following lexical definitions:\n\n imagnumber ::= (floatnumber | intpart) ("j" | "J")\n\nAn imaginary literal yields a complex number with a real part of 0.0.\nComplex numbers are represented as a pair of floating point numbers\nand have the same restrictions on their range. To create a complex\nnumber with a nonzero real part, add a floating point number to it,\ne.g., "(3+4j)". Some examples of imaginary literals:\n\n 3.14j 10.j 10j .001j 1e100j 3.14e-10j\n', + 'import': '\nThe "import" statement\n**********************\n\n import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*\n | "from" relative_module "import" identifier ["as" name]\n ( "," identifier ["as" name] )*\n | "from" relative_module "import" "(" identifier ["as" name]\n ( "," identifier ["as" name] )* [","] ")"\n | "from" module "import" "*"\n module ::= (identifier ".")* identifier\n relative_module ::= "."* module | "."+\n name ::= identifier\n\nThe basic import statement (no "from" clause) is executed in two\nsteps:\n\n1. find a module, loading and initializing it if necessary\n\n2. define a name or names in the local namespace for the scope\n where the "import" statement occurs.\n\nWhen the statement contains multiple clauses (separated by commas) the\ntwo steps are carried out separately for each clause, just as though\nthe clauses had been separated out into individiual import statements.\n\nThe details of the first step, finding and loading modules is\ndescribed in greater detail in the section on the *import system*,\nwhich also describes the various types of packages and modules that\ncan be imported, as well as all the hooks that can be used to\ncustomize the import system. Note that failures in this step may\nindicate either that the module could not be located, *or* that an\nerror occurred while initializing the module, which includes execution\nof the module\'s code.\n\nIf the requested module is retrieved successfully, it will be made\navailable in the local namespace in one of three ways:\n\n* If the module name is followed by "as", then the name following\n "as" is bound directly to the imported module.\n\n* If no other name is specified, and the module being imported is a\n top level module, the module\'s name is bound in the local namespace\n as a reference to the imported module\n\n* If the module being imported is *not* a top level module, then the\n name of the top level package that contains the module is bound in\n the local namespace as a reference to the top level package. The\n imported module must be accessed using its full qualified name\n rather than directly\n\nThe "from" form uses a slightly more complex process:\n\n1. find the module specified in the "from" clause loading and\n initializing it if necessary;\n\n2. for each of the identifiers specified in the "import" clauses:\n\n 1. check if the imported module has an attribute by that name\n\n 2. if not, attempt to import a submodule with that name and then\n check the imported module again for that attribute\n\n 3. if the attribute is not found, "ImportError" is raised.\n\n 4. otherwise, a reference to that value is bound in the local\n namespace, using the name in the "as" clause if it is present,\n otherwise using the attribute name\n\nExamples:\n\n import foo # foo imported and bound locally\n import foo.bar.baz # foo.bar.baz imported, foo bound locally\n import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb\n from foo.bar import baz # foo.bar.baz imported and bound as baz\n from foo import attr # foo imported and foo.attr bound as attr\n\nIf the list of identifiers is replaced by a star ("\'*\'"), all public\nnames defined in the module are bound in the local namespace for the\nscope where the "import" statement occurs.\n\nThe *public names* defined by a module are determined by checking the\nmodule\'s namespace for a variable named "__all__"; if defined, it must\nbe a sequence of strings which are names defined or imported by that\nmodule. The names given in "__all__" are all considered public and\nare required to exist. If "__all__" is not defined, the set of public\nnames includes all names found in the module\'s namespace which do not\nbegin with an underscore character ("\'_\'"). "__all__" should contain\nthe entire public API. It is intended to avoid accidentally exporting\nitems that are not part of the API (such as library modules which were\nimported and used within the module).\n\nThe "from" form with "*" may only occur in a module scope. The wild\ncard form of import --- "import *" --- is only allowed at the module\nlevel. Attempting to use it in class or function definitions will\nraise a "SyntaxError".\n\nWhen specifying what module to import you do not have to specify the\nabsolute name of the module. When a module or package is contained\nwithin another package it is possible to make a relative import within\nthe same top package without having to mention the package name. By\nusing leading dots in the specified module or package after "from" you\ncan specify how high to traverse up the current package hierarchy\nwithout specifying exact names. One leading dot means the current\npackage where the module making the import exists. Two dots means up\none package level. Three dots is up two levels, etc. So if you execute\n"from . import mod" from a module in the "pkg" package then you will\nend up importing "pkg.mod". If you execute "from ..subpkg2 import mod"\nfrom within "pkg.subpkg1" you will import "pkg.subpkg2.mod". The\nspecification for relative imports is contained within **PEP 328**.\n\n"importlib.import_module()" is provided to support applications that\ndetermine which modules need to be loaded dynamically.\n\n\nFuture statements\n=================\n\nA *future statement* is a directive to the compiler that a particular\nmodule should be compiled using syntax or semantics that will be\navailable in a specified future release of Python. The future\nstatement is intended to ease migration to future versions of Python\nthat introduce incompatible changes to the language. It allows use of\nthe new features on a per-module basis before the release in which the\nfeature becomes standard.\n\n future_statement ::= "from" "__future__" "import" feature ["as" name]\n ("," feature ["as" name])*\n | "from" "__future__" "import" "(" feature ["as" name]\n ("," feature ["as" name])* [","] ")"\n feature ::= identifier\n name ::= identifier\n\nA future statement must appear near the top of the module. The only\nlines that can appear before a future statement are:\n\n* the module docstring (if any),\n\n* comments,\n\n* blank lines, and\n\n* other future statements.\n\nThe features recognized by Python 3.0 are "absolute_import",\n"division", "generators", "unicode_literals", "print_function",\n"nested_scopes" and "with_statement". They are all redundant because\nthey are always enabled, and only kept for backwards compatibility.\n\nA future statement is recognized and treated specially at compile\ntime: Changes to the semantics of core constructs are often\nimplemented by generating different code. It may even be the case\nthat a new feature introduces new incompatible syntax (such as a new\nreserved word), in which case the compiler may need to parse the\nmodule differently. Such decisions cannot be pushed off until\nruntime.\n\nFor any given release, the compiler knows which feature names have\nbeen defined, and raises a compile-time error if a future statement\ncontains a feature not known to it.\n\nThe direct runtime semantics are the same as for any import statement:\nthere is a standard module "__future__", described later, and it will\nbe imported in the usual way at the time the future statement is\nexecuted.\n\nThe interesting runtime semantics depend on the specific feature\nenabled by the future statement.\n\nNote that there is nothing special about the statement:\n\n import __future__ [as name]\n\nThat is not a future statement; it\'s an ordinary import statement with\nno special semantics or syntax restrictions.\n\nCode compiled by calls to the built-in functions "exec()" and\n"compile()" that occur in a module "M" containing a future statement\nwill, by default, use the new syntax or semantics associated with the\nfuture statement. This can be controlled by optional arguments to\n"compile()" --- see the documentation of that function for details.\n\nA future statement typed at an interactive interpreter prompt will\ntake effect for the rest of the interpreter session. If an\ninterpreter is started with the *-i* option, is passed a script name\nto execute, and the script includes a future statement, it will be in\neffect in the interactive session started after the script is\nexecuted.\n\nSee also: **PEP 236** - Back to the __future__\n\n The original proposal for the __future__ mechanism.\n', + 'in': '\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. The\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of the differing types depends on whether either\nof the types provide explicit support for the comparison. Most\nnumeric types can be compared with one another. When cross-type\ncomparison is not supported, the comparison method returns\n"NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether a the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', 'integers': '\nInteger literals\n****************\n\nInteger literals are described by the following lexical definitions:\n\n integer ::= decimalinteger | octinteger | hexinteger | bininteger\n decimalinteger ::= nonzerodigit digit* | "0"+\n nonzerodigit ::= "1"..."9"\n digit ::= "0"..."9"\n octinteger ::= "0" ("o" | "O") octdigit+\n hexinteger ::= "0" ("x" | "X") hexdigit+\n bininteger ::= "0" ("b" | "B") bindigit+\n octdigit ::= "0"..."7"\n hexdigit ::= digit | "a"..."f" | "A"..."F"\n bindigit ::= "0" | "1"\n\nThere is no limit for the length of integer literals apart from what\ncan be stored in available memory.\n\nNote that leading zeros in a non-zero decimal number are not allowed.\nThis is for disambiguation with C-style octal literals, which Python\nused before version 3.0.\n\nSome examples of integer literals:\n\n 7 2147483647 0o177 0b100110111\n 3 79228162514264337593543950336 0o377 0x100000000\n 79228162514264337593543950336 0xdeadbeef\n', - 'lambda': '\nLambdas\n*******\n\n lambda_expr ::= "lambda" [parameter_list]: expression\n lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond\n\nLambda expressions (sometimes called lambda forms) have the same\nsyntactic position as expressions. They are a shorthand to create\nanonymous functions; the expression ``lambda arguments: expression``\nyields a function object. The unnamed object behaves like a function\nobject defined with\n\n def (arguments):\n return expression\n\nSee section *Function definitions* for the syntax of parameter lists.\nNote that functions created with lambda expressions cannot contain\nstatements or annotations.\n', + 'lambda': '\nLambdas\n*******\n\n lambda_expr ::= "lambda" [parameter_list]: expression\n lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond\n\nLambda expressions (sometimes called lambda forms) have the same\nsyntactic position as expressions. They are a shorthand to create\nanonymous functions; the expression "lambda arguments: expression"\nyields a function object. The unnamed object behaves like a function\nobject defined with\n\n def (arguments):\n return expression\n\nSee section *Function definitions* for the syntax of parameter lists.\nNote that functions created with lambda expressions cannot contain\nstatements or annotations.\n', 'lists': '\nList displays\n*************\n\nA list display is a possibly empty series of expressions enclosed in\nsquare brackets:\n\n list_display ::= "[" [expression_list | comprehension] "]"\n\nA list display yields a new list object, the contents being specified\nby either a list of expressions or a comprehension. When a comma-\nseparated list of expressions is supplied, its elements are evaluated\nfrom left to right and placed into the list object in that order.\nWhen a comprehension is supplied, the list is constructed from the\nelements resulting from the comprehension.\n', - 'naming': "\nNaming and binding\n******************\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the '**-c**' option) is a code block. The string argument passed\nto the built-in functions ``eval()`` and ``exec()`` is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block's execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block's *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as ``nonlocal``. If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a ``NameError`` exception is raised.\nIf the name refers to a local variable that has not been bound, a\n``UnboundLocalError`` exception is raised. ``UnboundLocalError`` is a\nsubclass of ``NameError``.\n\nThe following constructs bind names: formal parameters to functions,\n``import`` statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, ``for`` loop header, or\nafter ``as`` in a ``with`` statement or ``except`` clause. The\n``import`` statement of the form ``from ... import *`` binds all names\ndefined in the imported module, except those beginning with an\nunderscore. This form may only be used at the module level.\n\nA target occurring in a ``del`` statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the ``global`` statement occurs within a block, all uses of the\nname specified in the statement refer to the binding of that name in\nthe top-level namespace. Names are resolved in the top-level\nnamespace by searching the global namespace, i.e. the namespace of the\nmodule containing the code block, and the builtins namespace, the\nnamespace of the module ``builtins``. The global namespace is\nsearched first. If the name is not found there, the builtins\nnamespace is searched. The global statement must precede all uses of\nthe name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name ``__builtins__`` in its\nglobal namespace; this should be a dictionary or a module (in the\nlatter case the module's dictionary is used). By default, when in the\n``__main__`` module, ``__builtins__`` is the built-in module\n``builtins``; when in any other module, ``__builtins__`` is an alias\nfor the dictionary of the ``builtins`` module itself.\n``__builtins__`` can be set to a user-created dictionary to create a\nweak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n``__builtins__``; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should ``import``\nthe ``builtins`` module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n``__main__``.\n\nThe ``global`` statement has the same scope as a name binding\noperation in the same block. If the nearest enclosing scope for a\nfree variable contains a global statement, the free variable is\ntreated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n=================================\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- ``import *`` --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a ``SyntaxError``.\n\nThe ``eval()`` and ``exec()`` functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe ``exec()`` and ``eval()`` functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n", - 'nonlocal': '\nThe ``nonlocal`` statement\n**************************\n\n nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*\n\nThe ``nonlocal`` statement causes the listed identifiers to refer to\npreviously bound variables in the nearest enclosing scope. This is\nimportant because the default behavior for binding is to search the\nlocal namespace first. The statement allows encapsulated code to\nrebind variables outside of the local scope besides the global\n(module) scope.\n\nNames listed in a ``nonlocal`` statement, unlike to those listed in a\n``global`` statement, must refer to pre-existing bindings in an\nenclosing scope (the scope in which a new binding should be created\ncannot be determined unambiguously).\n\nNames listed in a ``nonlocal`` statement must not collide with pre-\nexisting bindings in the local scope.\n\nSee also:\n\n **PEP 3104** - Access to Names in Outer Scopes\n The specification for the ``nonlocal`` statement.\n', - 'numbers': "\nNumeric literals\n****************\n\nThere are three types of numeric literals: integers, floating point\nnumbers, and imaginary numbers. There are no complex literals\n(complex numbers can be formed by adding a real number and an\nimaginary number).\n\nNote that numeric literals do not include a sign; a phrase like ``-1``\nis actually an expression composed of the unary operator '``-``' and\nthe literal ``1``.\n", - 'numeric-types': "\nEmulating numeric types\n***********************\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations (``+``, ``-``, ``*``, ``/``, ``//``, ``%``,\n ``divmod()``, ``pow()``, ``**``, ``<<``, ``>>``, ``&``, ``^``,\n ``|``). For instance, to evaluate the expression ``x + y``, where\n *x* is an instance of a class that has an ``__add__()`` method,\n ``x.__add__(y)`` is called. The ``__divmod__()`` method should be\n the equivalent to using ``__floordiv__()`` and ``__mod__()``; it\n should not be related to ``__truediv__()``. Note that\n ``__pow__()`` should be defined to accept an optional third\n argument if the ternary version of the built-in ``pow()`` function\n is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return ``NotImplemented``.\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations (``+``, ``-``, ``*``, ``/``, ``//``, ``%``,\n ``divmod()``, ``pow()``, ``**``, ``<<``, ``>>``, ``&``, ``^``,\n ``|``) with reflected (swapped) operands. These functions are only\n called if the left operand does not support the corresponding\n operation and the operands are of different types. [2] For\n instance, to evaluate the expression ``x - y``, where *y* is an\n instance of a class that has an ``__rsub__()`` method,\n ``y.__rsub__(x)`` is called if ``x.__sub__(y)`` returns\n *NotImplemented*.\n\n Note that ternary ``pow()`` will not try calling ``__rpow__()``\n (the coercion rules would become too complicated).\n\n Note: If the right operand's type is a subclass of the left operand's\n type and that subclass provides the reflected method for the\n operation, this method will be called before the left operand's\n non-reflected method. This behavior allows subclasses to\n override their ancestors' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments (``+=``, ``-=``, ``*=``, ``/=``, ``//=``, ``%=``,\n ``**=``, ``<<=``, ``>>=``, ``&=``, ``^=``, ``|=``). These methods\n should attempt to do the operation in-place (modifying *self*) and\n return the result (which could be, but does not have to be,\n *self*). If a specific method is not defined, the augmented\n assignment falls back to the normal methods. For instance, to\n execute the statement ``x += y``, where *x* is an instance of a\n class that has an ``__iadd__()`` method, ``x.__iadd__(y)`` is\n called. If *x* is an instance of a class that does not define a\n ``__iadd__()`` method, ``x.__add__(y)`` and ``y.__radd__(x)`` are\n considered, as with the evaluation of ``x + y``.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations (``-``, ``+``,\n ``abs()`` and ``~``).\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions ``complex()``,\n ``int()``, ``float()`` and ``round()``. Should return a value of\n the appropriate type.\n\nobject.__index__(self)\n\n Called to implement ``operator.index()``. Also called whenever\n Python needs an integer object (such as in slicing, or in the\n built-in ``bin()``, ``hex()`` and ``oct()`` functions). Must return\n an integer.\n", - 'objects': '\nObjects, values and types\n*************************\n\n*Objects* are Python\'s abstraction for data. All data in a Python\nprogram is represented by objects or by relations between objects. (In\na sense, and in conformance to Von Neumann\'s model of a "stored\nprogram computer," code is also represented by objects.)\n\nEvery object has an identity, a type and a value. An object\'s\n*identity* never changes once it has been created; you may think of it\nas the object\'s address in memory. The \'``is``\' operator compares the\nidentity of two objects; the ``id()`` function returns an integer\nrepresenting its identity.\n\n**CPython implementation detail:** For CPython, ``id(x)`` is the\nmemory address where ``x`` is stored.\n\nAn object\'s type determines the operations that the object supports\n(e.g., "does it have a length?") and also defines the possible values\nfor objects of that type. The ``type()`` function returns an object\'s\ntype (which is an object itself). Like its identity, an object\'s\n*type* is also unchangeable. [1]\n\nThe *value* of some objects can change. Objects whose value can\nchange are said to be *mutable*; objects whose value is unchangeable\nonce they are created are called *immutable*. (The value of an\nimmutable container object that contains a reference to a mutable\nobject can change when the latter\'s value is changed; however the\ncontainer is still considered immutable, because the collection of\nobjects it contains cannot be changed. So, immutability is not\nstrictly the same as having an unchangeable value, it is more subtle.)\nAn object\'s mutability is determined by its type; for instance,\nnumbers, strings and tuples are immutable, while dictionaries and\nlists are mutable.\n\nObjects are never explicitly destroyed; however, when they become\nunreachable they may be garbage-collected. An implementation is\nallowed to postpone garbage collection or omit it altogether --- it is\na matter of implementation quality how garbage collection is\nimplemented, as long as no objects are collected that are still\nreachable.\n\n**CPython implementation detail:** CPython currently uses a reference-\ncounting scheme with (optional) delayed detection of cyclically linked\ngarbage, which collects most objects as soon as they become\nunreachable, but is not guaranteed to collect garbage containing\ncircular references. See the documentation of the ``gc`` module for\ninformation on controlling the collection of cyclic garbage. Other\nimplementations act differently and CPython may change. Do not depend\non immediate finalization of objects when they become unreachable (ex:\nalways close files).\n\nNote that the use of the implementation\'s tracing or debugging\nfacilities may keep objects alive that would normally be collectable.\nAlso note that catching an exception with a \'``try``...``except``\'\nstatement may keep objects alive.\n\nSome objects contain references to "external" resources such as open\nfiles or windows. It is understood that these resources are freed\nwhen the object is garbage-collected, but since garbage collection is\nnot guaranteed to happen, such objects also provide an explicit way to\nrelease the external resource, usually a ``close()`` method. Programs\nare strongly recommended to explicitly close such objects. The\n\'``try``...``finally``\' statement and the \'``with``\' statement provide\nconvenient ways to do this.\n\nSome objects contain references to other objects; these are called\n*containers*. Examples of containers are tuples, lists and\ndictionaries. The references are part of a container\'s value. In\nmost cases, when we talk about the value of a container, we imply the\nvalues, not the identities of the contained objects; however, when we\ntalk about the mutability of a container, only the identities of the\nimmediately contained objects are implied. So, if an immutable\ncontainer (like a tuple) contains a reference to a mutable object, its\nvalue changes if that mutable object is changed.\n\nTypes affect almost all aspects of object behavior. Even the\nimportance of object identity is affected in some sense: for immutable\ntypes, operations that compute new values may actually return a\nreference to any existing object with the same type and value, while\nfor mutable objects this is not allowed. E.g., after ``a = 1; b =\n1``, ``a`` and ``b`` may or may not refer to the same object with the\nvalue one, depending on the implementation, but after ``c = []; d =\n[]``, ``c`` and ``d`` are guaranteed to refer to two different,\nunique, newly created empty lists. (Note that ``c = d = []`` assigns\nthe same object to both ``c`` and ``d``.)\n', - 'operator-summary': '\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedences in Python,\nfrom lowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for comparisons, including\ntests, which all have the same precedence and chain from left to right\n--- see section *Comparisons* --- and exponentiation, which groups\nfrom right to left).\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| ``lambda`` | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| ``if`` -- ``else`` | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| ``or`` | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| ``and`` | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| ``not`` ``x`` | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| ``in``, ``not in``, ``is``, ``is not``, ``<``, | Comparisons, including membership |\n| ``<=``, ``>``, ``>=``, ``!=``, ``==`` | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| ``|`` | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| ``^`` | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| ``&`` | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| ``<<``, ``>>`` | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| ``+``, ``-`` | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| ``*``, ``/``, ``//``, ``%`` | Multiplication, division, remainder |\n| | [5] |\n+-------------------------------------------------+---------------------------------------+\n| ``+x``, ``-x``, ``~x`` | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| ``**`` | Exponentiation [6] |\n+-------------------------------------------------+---------------------------------------+\n| ``x[index]``, ``x[index:index]``, | Subscription, slicing, call, |\n| ``x(arguments...)``, ``x.attribute`` | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| ``(expressions...)``, ``[expressions...]``, | Binding or tuple display, list |\n| ``{key: value...}``, ``{expressions...}`` | display, dictionary display, set |\n| | display |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] While ``abs(x%y) < abs(y)`` is true mathematically, for floats it\n may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that ``-1e-100 % 1e100`` have the same\n sign as ``1e100``, the computed result is ``-1e-100 + 1e100``,\n which is numerically exactly equal to ``1e100``. The function\n ``math.fmod()`` returns a result whose sign matches the sign of\n the first argument instead, and so returns ``-1e-100`` in this\n case. Which approach is more appropriate depends on the\n application.\n\n[2] If x is very close to an exact integer multiple of y, it\'s\n possible for ``x//y`` to be one larger than ``(x-x%y)//y`` due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that ``divmod(x,y)[0] * y + x % y`` be very\n close to ``x``.\n\n[3] While comparisons between strings make sense at the byte level,\n they may be counter-intuitive to users. For example, the strings\n ``"\\u00C7"`` and ``"\\u0327\\u0043"`` compare differently, even\n though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using ``unicodedata.normalize()``.\n\n[4] Due to automatic garbage-collection, free lists, and the dynamic\n nature of descriptors, you may notice seemingly unusual behaviour\n in certain uses of the ``is`` operator, like those involving\n comparisons between instance methods, or constants. Check their\n documentation for more info.\n\n[5] The ``%`` operator is also used for string formatting; the same\n precedence applies.\n\n[6] The power operator ``**`` binds less tightly than an arithmetic or\n bitwise unary operator on its right, that is, ``2**-1`` is\n ``0.5``.\n', - 'pass': '\nThe ``pass`` statement\n**********************\n\n pass_stmt ::= "pass"\n\n``pass`` is a null operation --- when it is executed, nothing happens.\nIt is useful as a placeholder when a statement is required\nsyntactically, but no code needs to be executed, for example:\n\n def f(arg): pass # a function that does nothing (yet)\n\n class C: pass # a class with no methods (yet)\n', - 'power': '\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= primary ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): ``-1**2`` results in ``-1``.\n\nThe power operator has the same semantics as the built-in ``pow()``\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type, and the result is of that type.\n\nFor int operands, the result has the same type as the operands unless\nthe second argument is negative; in that case, all arguments are\nconverted to float and a float result is delivered. For example,\n``10**2`` returns ``100``, but ``10**-2`` returns ``0.01``.\n\nRaising ``0.0`` to a negative power results in a\n``ZeroDivisionError``. Raising a negative number to a fractional power\nresults in a ``complex`` number. (In earlier versions it raised a\n``ValueError``.)\n', - 'raise': '\nThe ``raise`` statement\n***********************\n\n raise_stmt ::= "raise" [expression ["from" expression]]\n\nIf no expressions are present, ``raise`` re-raises the last exception\nthat was active in the current scope. If no exception is active in\nthe current scope, a ``RuntimeError`` exception is raised indicating\nthat this is an error.\n\nOtherwise, ``raise`` evaluates the first expression as the exception\nobject. It must be either a subclass or an instance of\n``BaseException``. If it is a class, the exception instance will be\nobtained when needed by instantiating the class with no arguments.\n\nThe *type* of the exception is the exception instance\'s class, the\n*value* is the instance itself.\n\nA traceback object is normally created automatically when an exception\nis raised and attached to it as the ``__traceback__`` attribute, which\nis writable. You can create an exception and set your own traceback in\none step using the ``with_traceback()`` exception method (which\nreturns the same exception instance, with its traceback set to its\nargument), like so:\n\n raise Exception("foo occurred").with_traceback(tracebackobj)\n\nThe ``from`` clause is used for exception chaining: if given, the\nsecond *expression* must be another exception class or instance, which\nwill then be attached to the raised exception as the ``__cause__``\nattribute (which is writable). If the raised exception is not\nhandled, both exceptions will be printed:\n\n >>> try:\n ... print(1 / 0)\n ... except Exception as exc:\n ... raise RuntimeError("Something bad happened") from exc\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n The above exception was the direct cause of the following exception:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nA similar mechanism works implicitly if an exception is raised inside\nan exception handler: the previous exception is then attached as the\nnew exception\'s ``__context__`` attribute:\n\n >>> try:\n ... print(1 / 0)\n ... except:\n ... raise RuntimeError("Something bad happened")\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n During handling of the above exception, another exception occurred:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information about handling exceptions is in section\n*The try statement*.\n', - 'return': '\nThe ``return`` statement\n************************\n\n return_stmt ::= "return" [expression_list]\n\n``return`` may only occur syntactically nested in a function\ndefinition, not within a nested class definition.\n\nIf an expression list is present, it is evaluated, else ``None`` is\nsubstituted.\n\n``return`` leaves the current function call with the expression list\n(or ``None``) as return value.\n\nWhen ``return`` passes control out of a ``try`` statement with a\n``finally`` clause, that ``finally`` clause is executed before really\nleaving the function.\n\nIn a generator function, the ``return`` statement indicates that the\ngenerator is done and will cause ``StopIteration`` to be raised. The\nreturned value (if any) is used as an argument to construct\n``StopIteration`` and becomes the ``StopIteration.value`` attribute.\n', - 'sequence-types': "\nEmulating container types\n*************************\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which ``0 <= k < N``\nwhere *N* is the length of the sequence, or slice objects, which\ndefine a range of items. It is also recommended that mappings provide\nthe methods ``keys()``, ``values()``, ``items()``, ``get()``,\n``clear()``, ``setdefault()``, ``pop()``, ``popitem()``, ``copy()``,\nand ``update()`` behaving similar to those for Python's standard\ndictionary objects. The ``collections`` module provides a\n``MutableMapping`` abstract base class to help create those methods\nfrom a base set of ``__getitem__()``, ``__setitem__()``,\n``__delitem__()``, and ``keys()``. Mutable sequences should provide\nmethods ``append()``, ``count()``, ``index()``, ``extend()``,\n``insert()``, ``pop()``, ``remove()``, ``reverse()`` and ``sort()``,\nlike Python standard list objects. Finally, sequence types should\nimplement addition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods ``__add__()``, ``__radd__()``,\n``__iadd__()``, ``__mul__()``, ``__rmul__()`` and ``__imul__()``\ndescribed below; they should not define other numerical operators. It\nis recommended that both mappings and sequences implement the\n``__contains__()`` method to allow efficient use of the ``in``\noperator; for mappings, ``in`` should search the mapping's keys; for\nsequences, it should search through the values. It is further\nrecommended that both mappings and sequences implement the\n``__iter__()`` method to allow efficient iteration through the\ncontainer; for mappings, ``__iter__()`` should be the same as\n``keys()``; for sequences, it should iterate through the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function ``len()``. Should return\n the length of the object, an integer ``>=`` 0. Also, an object\n that doesn't define a ``__bool__()`` method and whose ``__len__()``\n method returns zero is considered to be false in a Boolean context.\n\nNote: Slicing is done exclusively with the following three methods. A\n call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with\n ``None``.\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of ``self[key]``. For sequence\n types, the accepted keys should be integers and slice objects.\n Note that the special interpretation of negative indexes (if the\n class wishes to emulate a sequence type) is up to the\n ``__getitem__()`` method. If *key* is of an inappropriate type,\n ``TypeError`` may be raised; if of a value outside the set of\n indexes for the sequence (after any special interpretation of\n negative values), ``IndexError`` should be raised. For mapping\n types, if *key* is missing (not in the container), ``KeyError``\n should be raised.\n\n Note: ``for`` loops expect that an ``IndexError`` will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to ``self[key]``. Same note as for\n ``__getitem__()``. This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the ``__getitem__()`` method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of ``self[key]``. Same note as for\n ``__getitem__()``. This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the ``__getitem__()``\n method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method ``keys()``.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the ``reversed()`` built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the ``__reversed__()`` method is not provided, the\n ``reversed()`` built-in will fall back to using the sequence\n protocol (``__len__()`` and ``__getitem__()``). Objects that\n support the sequence protocol should only provide\n ``__reversed__()`` if they can provide an implementation that is\n more efficient than the one provided by ``reversed()``.\n\nThe membership test operators (``in`` and ``not in``) are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don't define ``__contains__()``, the membership\n test first tries iteration via ``__iter__()``, then the old\n sequence iteration protocol via ``__getitem__()``, see *this\n section in the language reference*.\n", - 'shifting': '\nShifting operations\n*******************\n\nThe shifting operations have lower priority than the arithmetic\noperations:\n\n shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr\n\nThese operators accept integers as arguments. They shift the first\nargument to the left or right by the number of bits given by the\nsecond argument.\n\nA right shift by *n* bits is defined as floor division by\n``pow(2,n)``. A left shift by *n* bits is defined as multiplication\nwith ``pow(2,n)``.\n\nNote: In the current implementation, the right-hand operand is required to\n be at most ``sys.maxsize``. If the right-hand operand is larger\n than ``sys.maxsize`` an ``OverflowError`` exception is raised.\n', - 'slicings': '\nSlicings\n********\n\nA slicing selects a range of items in a sequence object (e.g., a\nstring, tuple or list). Slicings may be used as expressions or as\ntargets in assignment or ``del`` statements. The syntax for a\nslicing:\n\n slicing ::= primary "[" slice_list "]"\n slice_list ::= slice_item ("," slice_item)* [","]\n slice_item ::= expression | proper_slice\n proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]\n lower_bound ::= expression\n upper_bound ::= expression\n stride ::= expression\n\nThere is ambiguity in the formal syntax here: anything that looks like\nan expression list also looks like a slice list, so any subscription\ncan be interpreted as a slicing. Rather than further complicating the\nsyntax, this is disambiguated by defining that in this case the\ninterpretation as a subscription takes priority over the\ninterpretation as a slicing (this is the case if the slice list\ncontains no proper slice).\n\nThe semantics for a slicing are as follows. The primary must evaluate\nto a mapping object, and it is indexed (using the same\n``__getitem__()`` method as normal subscription) with a key that is\nconstructed from the slice list, as follows. If the slice list\ncontains at least one comma, the key is a tuple containing the\nconversion of the slice items; otherwise, the conversion of the lone\nslice item is the key. The conversion of a slice item that is an\nexpression is that expression. The conversion of a proper slice is a\nslice object (see section *The standard type hierarchy*) whose\n``start``, ``stop`` and ``step`` attributes are the values of the\nexpressions given as lower bound, upper bound and stride,\nrespectively, substituting ``None`` for missing expressions.\n', - 'specialattrs': '\nSpecial Attributes\n******************\n\nThe implementation adds a few special read-only attributes to several\nobject types, where they are relevant. Some of these are not reported\nby the ``dir()`` built-in function.\n\nobject.__dict__\n\n A dictionary or other mapping object used to store an object\'s\n (writable) attributes.\n\ninstance.__class__\n\n The class to which a class instance belongs.\n\nclass.__bases__\n\n The tuple of base classes of a class object.\n\nclass.__name__\n\n The name of the class or type.\n\nclass.__qualname__\n\n The *qualified name* of the class or type.\n\n New in version 3.3.\n\nclass.__mro__\n\n This attribute is a tuple of classes that are considered when\n looking for base classes during method resolution.\n\nclass.mro()\n\n This method can be overridden by a metaclass to customize the\n method resolution order for its instances. It is called at class\n instantiation, and its result is stored in ``__mro__``.\n\nclass.__subclasses__()\n\n Each class keeps a list of weak references to its immediate\n subclasses. This method returns a list of all those references\n still alive. Example:\n\n >>> int.__subclasses__()\n []\n\n-[ Footnotes ]-\n\n[1] Additional information on these special methods may be found in\n the Python Reference Manual (*Basic customization*).\n\n[2] As a consequence, the list ``[1, 2]`` is considered equal to\n ``[1.0, 2.0]``, and similarly for tuples.\n\n[3] They must have since the parser can\'t tell the type of the\n operands.\n\n[4] Cased characters are those with general category property being\n one of "Lu" (Letter, uppercase), "Ll" (Letter, lowercase), or "Lt"\n (Letter, titlecase).\n\n[5] To format only a tuple you should therefore provide a singleton\n tuple whose only element is the tuple to be formatted.\n', - 'specialnames': '\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named ``__getitem__()``, and ``x`` is an instance of this\nclass, then ``x[i]`` is roughly equivalent to ``type(x).__getitem__(x,\ni)``. Except where mentioned, attempts to execute an operation raise\nan exception when no appropriate method is defined (typically\n``AttributeError`` or ``TypeError``).\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n``NodeList`` interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. ``__new__()`` is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of ``__new__()`` should be the new object instance (usually\n an instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s ``__new__()`` method using\n ``super(currentclass, cls).__new__(cls[, ...])`` with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If ``__new__()`` returns an instance of *cls*, then the new\n instance\'s ``__init__()`` method will be invoked like\n ``__init__(self[, ...])``, where *self* is the new instance and the\n remaining arguments are the same as were passed to ``__new__()``.\n\n If ``__new__()`` does not return an instance of *cls*, then the new\n instance\'s ``__init__()`` method will not be invoked.\n\n ``__new__()`` is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called when the instance is created. The arguments are those\n passed to the class constructor expression. If a base class has an\n ``__init__()`` method, the derived class\'s ``__init__()`` method,\n if any, must explicitly call it to ensure proper initialization of\n the base class part of the instance; for example:\n ``BaseClass.__init__(self, [args...])``. As a special constraint\n on constructors, no value may be returned; doing so will cause a\n ``TypeError`` to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a ``__del__()`` method,\n the derived class\'s ``__del__()`` method, if any, must explicitly\n call it to ensure proper deletion of the base class part of the\n instance. Note that it is possible (though not recommended!) for\n the ``__del__()`` method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n ``__del__()`` methods are called for objects that still exist when\n the interpreter exits.\n\n Note: ``del x`` doesn\'t directly call ``x.__del__()`` --- the former\n decrements the reference count for ``x`` by one, and the latter\n is only called when ``x``\'s reference count reaches zero. Some\n common situations that may prevent the reference count of an\n object from going to zero include: circular references between\n objects (e.g., a doubly-linked list or a tree data structure with\n parent and child pointers); a reference to the object on the\n stack frame of a function that caught an exception (the traceback\n stored in ``sys.exc_info()[2]`` keeps the stack frame alive); or\n a reference to the object on the stack frame that raised an\n unhandled exception in interactive mode (the traceback stored in\n ``sys.last_traceback`` keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing ``None`` in\n ``sys.last_traceback``. Circular references which are garbage are\n detected when the option cycle detector is enabled (it\'s on by\n default), but can only be cleaned up if there are no Python-\n level ``__del__()`` methods involved. Refer to the documentation\n for the ``gc`` module for more information about how\n ``__del__()`` methods are handled by the cycle detector,\n particularly the description of the ``garbage`` value.\n\n Warning: Due to the precarious circumstances under which ``__del__()``\n methods are invoked, exceptions that occur during their execution\n are ignored, and a warning is printed to ``sys.stderr`` instead.\n Also, when ``__del__()`` is invoked in response to a module being\n deleted (e.g., when execution of the program is done), other\n globals referenced by the ``__del__()`` method may already have\n been deleted or in the process of being torn down (e.g. the\n import machinery shutting down). For this reason, ``__del__()``\n methods should do the absolute minimum needed to maintain\n external invariants. Starting with version 1.5, Python\n guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the ``__del__()`` method is called.\n\nobject.__repr__(self)\n\n Called by the ``repr()`` built-in function to compute the\n "official" string representation of an object. If at all possible,\n this should look like a valid Python expression that could be used\n to recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n ``<...some useful description...>`` should be returned. The return\n value must be a string object. If a class defines ``__repr__()``\n but not ``__str__()``, then ``__repr__()`` is also used when an\n "informal" string representation of instances of that class is\n required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by ``str(object)`` and the built-in functions ``format()``\n and ``print()`` to compute the "informal" or nicely printable\n string representation of an object. The return value must be a\n *string* object.\n\n This method differs from ``object.__repr__()`` in that there is no\n expectation that ``__str__()`` return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type ``object``\n calls ``object.__repr__()``.\n\nobject.__bytes__(self)\n\n Called by ``bytes()`` to compute a byte-string representation of an\n object. This should return a ``bytes`` object.\n\nobject.__format__(self, format_spec)\n\n Called by the ``format()`` built-in function (and by extension, the\n ``str.format()`` method of class ``str``) to produce a "formatted"\n string representation of an object. The ``format_spec`` argument is\n a string that contains a description of the formatting options\n desired. The interpretation of the ``format_spec`` argument is up\n to the type implementing ``__format__()``, however most classes\n will either delegate formatting to one of the built-in types, or\n use a similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: ``xy`` calls ``x.__gt__(y)``, and ``x>=y`` calls\n ``x.__ge__(y)``.\n\n A rich comparison method may return the singleton\n ``NotImplemented`` if it does not implement the operation for a\n given pair of arguments. By convention, ``False`` and ``True`` are\n returned for a successful comparison. However, these methods can\n return any value, so if the comparison operator is used in a\n Boolean context (e.g., in the condition of an ``if`` statement),\n Python will call ``bool()`` on the value to determine if the result\n is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of ``x==y`` does not imply that ``x!=y`` is false.\n Accordingly, when defining ``__eq__()``, one should also define\n ``__ne__()`` so that the operators will behave as expected. See\n the paragraph on ``__hash__()`` for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, ``__lt__()`` and ``__gt__()`` are each\n other\'s reflection, ``__le__()`` and ``__ge__()`` are each other\'s\n reflection, and ``__eq__()`` and ``__ne__()`` are their own\n reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see ``functools.total_ordering()``.\n\nobject.__hash__(self)\n\n Called by built-in function ``hash()`` and for operations on\n members of hashed collections including ``set``, ``frozenset``, and\n ``dict``. ``__hash__()`` should return an integer. The only\n required property is that objects which compare equal have the same\n hash value; it is advised to somehow mix together (e.g. using\n exclusive or) the hash values for the components of the object that\n also play a part in comparison of objects.\n\n Note: ``hash()`` truncates the value returned from an object\'s custom\n ``__hash__()`` method to the size of a ``Py_ssize_t``. This is\n typically 8 bytes on 64-bit builds and 4 bytes on 32-bit builds.\n If an object\'s ``__hash__()`` must interoperate on builds of\n different bit sizes, be sure to check the width on all supported\n builds. An easy way to do this is with ``python -c "import sys;\n print(sys.hash_info.width)"``\n\n If a class does not define an ``__eq__()`` method it should not\n define a ``__hash__()`` operation either; if it defines\n ``__eq__()`` but not ``__hash__()``, its instances will not be\n usable as items in hashable collections. If a class defines\n mutable objects and implements an ``__eq__()`` method, it should\n not implement ``__hash__()``, since the implementation of hashable\n collections requires that a key\'s hash value is immutable (if the\n object\'s hash value changes, it will be in the wrong hash bucket).\n\n User-defined classes have ``__eq__()`` and ``__hash__()`` methods\n by default; with them, all objects compare unequal (except with\n themselves) and ``x.__hash__()`` returns an appropriate value such\n that ``x == y`` implies both that ``x is y`` and ``hash(x) ==\n hash(y)``.\n\n A class that overrides ``__eq__()`` and does not define\n ``__hash__()`` will have its ``__hash__()`` implicitly set to\n ``None``. When the ``__hash__()`` method of a class is ``None``,\n instances of the class will raise an appropriate ``TypeError`` when\n a program attempts to retrieve their hash value, and will also be\n correctly identified as unhashable when checking ``isinstance(obj,\n collections.Hashable``).\n\n If a class that overrides ``__eq__()`` needs to retain the\n implementation of ``__hash__()`` from a parent class, the\n interpreter must be told this explicitly by setting ``__hash__ =\n .__hash__``.\n\n If a class that does not override ``__eq__()`` wishes to suppress\n hash support, it should include ``__hash__ = None`` in the class\n definition. A class which defines its own ``__hash__()`` that\n explicitly raises a ``TypeError`` would be incorrectly identified\n as hashable by an ``isinstance(obj, collections.Hashable)`` call.\n\n Note: By default, the ``__hash__()`` values of str, bytes and datetime\n objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also ``PYTHONHASHSEED``.\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n ``bool()``; should return ``False`` or ``True``. When this method\n is not defined, ``__len__()`` is called, if it is defined, and the\n object is considered true if its result is nonzero. If a class\n defines neither ``__len__()`` nor ``__bool__()``, all its instances\n are considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of ``x.name``)\nfor class instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for ``self``). ``name`` is the attribute name.\n This method should return the (computed) attribute value or raise\n an ``AttributeError`` exception.\n\n Note that if the attribute is found through the normal mechanism,\n ``__getattr__()`` is not called. (This is an intentional asymmetry\n between ``__getattr__()`` and ``__setattr__()``.) This is done both\n for efficiency reasons and because otherwise ``__getattr__()``\n would have no way to access other attributes of the instance. Note\n that at least for instance variables, you can fake total control by\n not inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n ``__getattribute__()`` method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines\n ``__getattr__()``, the latter will not be called unless\n ``__getattribute__()`` either calls it explicitly or raises an\n ``AttributeError``. This method should return the (computed)\n attribute value or raise an ``AttributeError`` exception. In order\n to avoid infinite recursion in this method, its implementation\n should always call the base class method with the same name to\n access any attributes it needs, for example,\n ``object.__getattribute__(self, name)``.\n\n Note: This method may still be bypassed when looking up special methods\n as the result of implicit invocation via language syntax or\n built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If ``__setattr__()`` wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n ``object.__setattr__(self, name, value)``.\n\nobject.__delattr__(self, name)\n\n Like ``__setattr__()`` but for attribute deletion instead of\n assignment. This should only be implemented if ``del obj.name`` is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when ``dir()`` is called on the object. A sequence must be\n returned. ``dir()`` converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' ``__dict__``.\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or ``None`` when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an\n ``AttributeError`` exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: ``__get__()``, ``__set__()``, and\n``__delete__()``. If any of those methods are defined for an object,\nit is said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, ``a.x`` has a\nlookup chain starting with ``a.__dict__[\'x\']``, then\n``type(a).__dict__[\'x\']``, and continuing through the base classes of\n``type(a)`` excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, ``a.x``.\nHow the arguments are assembled depends on ``a``:\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: ``x.__get__(a)``.\n\nInstance Binding\n If binding to an object instance, ``a.x`` is transformed into the\n call: ``type(a).__dict__[\'x\'].__get__(a, type(a))``.\n\nClass Binding\n If binding to a class, ``A.x`` is transformed into the call:\n ``A.__dict__[\'x\'].__get__(None, A)``.\n\nSuper Binding\n If ``a`` is an instance of ``super``, then the binding ``super(B,\n obj).m()`` searches ``obj.__class__.__mro__`` for the base class\n ``A`` immediately preceding ``B`` and then invokes the descriptor\n with the call: ``A.__dict__[\'m\'].__get__(obj, obj.__class__)``.\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of ``__get__()``, ``__set__()`` and ``__delete__()``.\nIf it does not define ``__get__()``, then accessing the attribute will\nreturn the descriptor object itself unless there is a value in the\nobject\'s instance dictionary. If the descriptor defines ``__set__()``\nand/or ``__delete__()``, it is a data descriptor; if it defines\nneither, it is a non-data descriptor. Normally, data descriptors\ndefine both ``__get__()`` and ``__set__()``, while non-data\ndescriptors have just the ``__get__()`` method. Data descriptors with\n``__set__()`` and ``__get__()`` defined always override a redefinition\nin an instance dictionary. In contrast, non-data descriptors can be\noverridden by instances.\n\nPython methods (including ``staticmethod()`` and ``classmethod()``)\nare implemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe ``property()`` function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n class, *__slots__* reserves space for the declared variables and\n prevents the automatic creation of *__dict__* and *__weakref__* for\n each instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises ``AttributeError``. If\n dynamic assignment of new variables is desired, then add\n ``\'__dict__\'`` to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes defining\n *__slots__* do not support weak references to its instances. If weak\n reference support is needed, then add ``\'__weakref__\'`` to the\n sequence of strings in the *__slots__* declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the instance\n variable defined by the base class slot is inaccessible (except by\n retrieving its descriptor directly from the base class). This\n renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as ``int``, ``str`` and\n ``tuple``.\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings may\n also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using ``type()``. The class body\nis executed in a new namespace and the class name is bound locally to\nthe result of ``type(name, bases, namespace)``.\n\nThe class creation process can be customised by passing the\n``metaclass`` keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both ``MyClass`` and ``MySubclass`` are\ninstances of ``Meta``:\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then ``type()`` is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n ``type()``, then it is used directly as the metaclass\n\n* if an instance of ``type()`` is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. ``type(cls)``) of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with ``TypeError``.\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a ``__prepare__``\nattribute, it is called as ``namespace = metaclass.__prepare__(name,\nbases, **kwds)`` (where the additional keyword arguments, if any, come\nfrom the class definition).\n\nIf the metaclass has no ``__prepare__`` attribute, then the class\nnamespace is initialised as an empty ``dict()`` instance.\n\nSee also:\n\n **PEP 3115** - Metaclasses in Python 3000\n Introduced the ``__prepare__`` namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as ``exec(body, globals(),\nnamespace)``. The key difference from a normal call to ``exec()`` is\nthat lexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling ``metaclass(name, bases,\nnamespace, **kwds)`` (the additional keywords passed here are the same\nas those passed to ``__prepare__``).\n\nThis class object is the one that will be referenced by the zero-\nargument form of ``super()``. ``__class__`` is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either ``__class__`` or ``super``. This allows the zero argument\nform of ``super()`` to correctly identify the class being defined\nbased on lexical scoping, while the class or instance that was used to\nmake the current call is identified based on the first argument passed\nto the method.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also:\n\n **PEP 3135** - New super\n Describes the implicit ``__class__`` closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n``collections.OrderedDict`` to remember the order that class members\nwere defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s ``__prepare__()`` method which returns an\nempty ``collections.OrderedDict``. That mapping records the methods\nand attributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s ``__new__()`` method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called ``members``.\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n``isinstance()`` and ``issubclass()`` built-in functions.\n\nIn particular, the metaclass ``abc.ABCMeta`` implements these methods\nin order to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n ``isinstance(instance, class)``.\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n ``issubclass(subclass, class)``.\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also:\n\n **PEP 3119** - Introducing Abstract Base Classes\n Includes the specification for customizing ``isinstance()`` and\n ``issubclass()`` behavior through ``__instancecheck__()`` and\n ``__subclasscheck__()``, with motivation for this functionality\n in the context of adding Abstract Base Classes (see the ``abc``\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, ``x(arg1, arg2, ...)`` is a shorthand for\n ``x.__call__(arg1, arg2, ...)``.\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which ``0 <= k < N``\nwhere *N* is the length of the sequence, or slice objects, which\ndefine a range of items. It is also recommended that mappings provide\nthe methods ``keys()``, ``values()``, ``items()``, ``get()``,\n``clear()``, ``setdefault()``, ``pop()``, ``popitem()``, ``copy()``,\nand ``update()`` behaving similar to those for Python\'s standard\ndictionary objects. The ``collections`` module provides a\n``MutableMapping`` abstract base class to help create those methods\nfrom a base set of ``__getitem__()``, ``__setitem__()``,\n``__delitem__()``, and ``keys()``. Mutable sequences should provide\nmethods ``append()``, ``count()``, ``index()``, ``extend()``,\n``insert()``, ``pop()``, ``remove()``, ``reverse()`` and ``sort()``,\nlike Python standard list objects. Finally, sequence types should\nimplement addition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods ``__add__()``, ``__radd__()``,\n``__iadd__()``, ``__mul__()``, ``__rmul__()`` and ``__imul__()``\ndescribed below; they should not define other numerical operators. It\nis recommended that both mappings and sequences implement the\n``__contains__()`` method to allow efficient use of the ``in``\noperator; for mappings, ``in`` should search the mapping\'s keys; for\nsequences, it should search through the values. It is further\nrecommended that both mappings and sequences implement the\n``__iter__()`` method to allow efficient iteration through the\ncontainer; for mappings, ``__iter__()`` should be the same as\n``keys()``; for sequences, it should iterate through the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function ``len()``. Should return\n the length of the object, an integer ``>=`` 0. Also, an object\n that doesn\'t define a ``__bool__()`` method and whose ``__len__()``\n method returns zero is considered to be false in a Boolean context.\n\nNote: Slicing is done exclusively with the following three methods. A\n call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with\n ``None``.\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of ``self[key]``. For sequence\n types, the accepted keys should be integers and slice objects.\n Note that the special interpretation of negative indexes (if the\n class wishes to emulate a sequence type) is up to the\n ``__getitem__()`` method. If *key* is of an inappropriate type,\n ``TypeError`` may be raised; if of a value outside the set of\n indexes for the sequence (after any special interpretation of\n negative values), ``IndexError`` should be raised. For mapping\n types, if *key* is missing (not in the container), ``KeyError``\n should be raised.\n\n Note: ``for`` loops expect that an ``IndexError`` will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to ``self[key]``. Same note as for\n ``__getitem__()``. This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the ``__getitem__()`` method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of ``self[key]``. Same note as for\n ``__getitem__()``. This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the ``__getitem__()``\n method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method ``keys()``.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the ``reversed()`` built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the ``__reversed__()`` method is not provided, the\n ``reversed()`` built-in will fall back to using the sequence\n protocol (``__len__()`` and ``__getitem__()``). Objects that\n support the sequence protocol should only provide\n ``__reversed__()`` if they can provide an implementation that is\n more efficient than the one provided by ``reversed()``.\n\nThe membership test operators (``in`` and ``not in``) are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define ``__contains__()``, the membership\n test first tries iteration via ``__iter__()``, then the old\n sequence iteration protocol via ``__getitem__()``, see *this\n section in the language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations (``+``, ``-``, ``*``, ``/``, ``//``, ``%``,\n ``divmod()``, ``pow()``, ``**``, ``<<``, ``>>``, ``&``, ``^``,\n ``|``). For instance, to evaluate the expression ``x + y``, where\n *x* is an instance of a class that has an ``__add__()`` method,\n ``x.__add__(y)`` is called. The ``__divmod__()`` method should be\n the equivalent to using ``__floordiv__()`` and ``__mod__()``; it\n should not be related to ``__truediv__()``. Note that\n ``__pow__()`` should be defined to accept an optional third\n argument if the ternary version of the built-in ``pow()`` function\n is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return ``NotImplemented``.\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations (``+``, ``-``, ``*``, ``/``, ``//``, ``%``,\n ``divmod()``, ``pow()``, ``**``, ``<<``, ``>>``, ``&``, ``^``,\n ``|``) with reflected (swapped) operands. These functions are only\n called if the left operand does not support the corresponding\n operation and the operands are of different types. [2] For\n instance, to evaluate the expression ``x - y``, where *y* is an\n instance of a class that has an ``__rsub__()`` method,\n ``y.__rsub__(x)`` is called if ``x.__sub__(y)`` returns\n *NotImplemented*.\n\n Note that ternary ``pow()`` will not try calling ``__rpow__()``\n (the coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left operand\'s\n type and that subclass provides the reflected method for the\n operation, this method will be called before the left operand\'s\n non-reflected method. This behavior allows subclasses to\n override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments (``+=``, ``-=``, ``*=``, ``/=``, ``//=``, ``%=``,\n ``**=``, ``<<=``, ``>>=``, ``&=``, ``^=``, ``|=``). These methods\n should attempt to do the operation in-place (modifying *self*) and\n return the result (which could be, but does not have to be,\n *self*). If a specific method is not defined, the augmented\n assignment falls back to the normal methods. For instance, to\n execute the statement ``x += y``, where *x* is an instance of a\n class that has an ``__iadd__()`` method, ``x.__iadd__(y)`` is\n called. If *x* is an instance of a class that does not define a\n ``__iadd__()`` method, ``x.__add__(y)`` and ``y.__radd__(x)`` are\n considered, as with the evaluation of ``x + y``.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations (``-``, ``+``,\n ``abs()`` and ``~``).\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions ``complex()``,\n ``int()``, ``float()`` and ``round()``. Should return a value of\n the appropriate type.\n\nobject.__index__(self)\n\n Called to implement ``operator.index()``. Also called whenever\n Python needs an integer object (such as in slicing, or in the\n built-in ``bin()``, ``hex()`` and ``oct()`` functions). Must return\n an integer.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a ``with`` statement. The context\nmanager handles the entry into, and the exit from, the desired runtime\ncontext for the execution of the block of code. Context managers are\nnormally invoked using the ``with`` statement (described in section\n*The with statement*), but can also be used by directly invoking their\nmethods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The ``with``\n statement will bind this method\'s return value to the target(s)\n specified in the ``as`` clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be ``None``.\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that ``__exit__()`` methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as ``__hash__()`` and ``__repr__()`` that are implemented\nby all objects, including type objects. If the implicit lookup of\nthese methods used the conventional lookup process, they would fail\nwhen invoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe ``__getattribute__()`` method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the ``__getattribute__()`` machinery in this fashion\nprovides significant scope for speed optimisations within the\ninterpreter, at the cost of some flexibility in the handling of\nspecial methods (the special method *must* be set on the class object\nitself in order to be consistently invoked by the interpreter).\n\n-[ Footnotes ]-\n\n[1] It *is* possible in some cases to change an object\'s type, under\n certain controlled conditions. It generally isn\'t a good idea\n though, since it can lead to some very strange behaviour if it is\n handled incorrectly.\n\n[2] For operands of the same type, it is assumed that if the non-\n reflected method (such as ``__add__()``) fails the operation is\n not supported, which is why the reflected method is not called.\n', - 'string-methods': '\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see ``str.format()``,\n*Format String Syntax* and *String Formatting*) and the other based on\nC ``printf`` style formatting that handles a narrower range of types\nand is slightly harder to use correctly, but is often faster for the\ncases it can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the ``re`` module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter ``\'\xc3\x9f\'`` is equivalent to\n ``"ss"``. Since it is already lowercase, ``lower()`` would do\n nothing to ``\'\xc3\x9f\'``; ``casefold()`` converts it to ``"ss"``.\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is a space).\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is ``\'utf-8\'``. *errors* may be given to set a different\n error handling scheme. The default for *errors* is ``\'strict\'``,\n meaning that encoding errors raise a ``UnicodeError``. Other\n possible values are ``\'ignore\'``, ``\'replace\'``,\n ``\'xmlcharrefreplace\'``, ``\'backslashreplace\'`` and any other name\n registered via ``codecs.register_error()``, see section *Codec Base\n Classes*. For a list of possible encodings, see section *Standard\n Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return ``True`` if the string ends with the specified *suffix*,\n otherwise return ``False``. *suffix* can also be a tuple of\n suffixes to look for. With optional *start*, test beginning at\n that position. With optional *end*, stop comparing at that\n position.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab (``\\t``), one or more space characters are inserted in the\n result until the current column is equal to the next tab position.\n (The tab character itself is not copied.) If the character is a\n newline (``\\n``) or return (``\\r``), it is copied and the current\n column is reset to zero. Any other character is copied unchanged\n and the current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice ``s[start:end]``.\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return ``-1`` if *sub* is not found.\n\n Note: The ``find()`` method should be used only if you need to know the\n position of *sub*. To check if *sub* is a substring or not, use\n the ``in`` operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces ``{}``. Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to ``str.format(**mapping)``, except that ``mapping`` is\n used directly and not copied to a ``dict`` . This is useful if for\n example ``mapping`` is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like ``find()``, but raise ``ValueError`` when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character\n ``c`` is alphanumeric if one of the following returns ``True``:\n ``c.isalpha()``, ``c.isdecimal()``, ``c.isdigit()``, or\n ``c.isnumeric()``.\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use ``keyword.iskeyword()`` to test for reserved identifiers such\n as ``def`` and ``class``.\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when ``repr()`` is\n invoked on a string. It has no bearing on the handling of strings\n written to ``sys.stdout`` or ``sys.stderr``.)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A ``TypeError`` will be raised if there are\n any non-string values in *iterable*, including ``bytes`` objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to ``len(s)``.\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or ``None``, the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n ``str.translate()``.\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within ``s[start:end]``.\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return ``-1`` on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like ``rfind()`` but raises ``ValueError`` when the substring *sub*\n is not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to ``len(s)``.\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n ``None``, any whitespace string is a separator. Except for\n splitting from the right, ``rsplit()`` behaves like ``split()``\n which is described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or ``None``, the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most ``maxsplit+1``\n elements). If *maxsplit* is not specified or ``-1``, then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n ``\'1,,2\'.split(\',\')`` returns ``[\'1\', \'\', \'2\']``). The *sep*\n argument may consist of multiple characters (for example,\n ``\'1<>2<>3\'.split(\'<>\')`` returns ``[\'1\', \'2\', \'3\']``). Splitting\n an empty string with a specified separator returns ``[\'\']``.\n\n If *sep* is not specified or is ``None``, a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a ``None`` separator returns\n ``[]``.\n\n For example, ``\' 1 2 3 \'.split()`` returns ``[\'1\', \'2\', \'3\']``,\n and ``\' 1 2 3 \'.split(None, 1)`` returns ``[\'1\', \'2 3 \']``.\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example, ``\'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()`` returns\n ``[\'ab c\', \'\', \'de fg\', \'kl\']``, while the same call with\n ``splitlines(True)`` returns ``[\'ab c\\n\', \'\\n\', \'de fg\\r\',\n \'kl\\r\\n\']``.\n\n Unlike ``split()`` when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line.\n\nstr.startswith(prefix[, start[, end]])\n\n Return ``True`` if string starts with the *prefix*, otherwise\n return ``False``. *prefix* can also be a tuple of prefixes to look\n for. With optional *start*, test string beginning at that\n position. With optional *end*, stop comparing string at that\n position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or ``None``, the\n *chars* argument defaults to removing whitespace. The *chars*\n argument is not a prefix or suffix; rather, all combinations of its\n values are stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n ``s.swapcase().swapcase() == s``.\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(map)\n\n Return a copy of the *s* where all characters have been mapped\n through the *map* which must be a dictionary of Unicode ordinals\n (integers) to Unicode ordinals, strings or ``None``. Unmapped\n characters are left untouched. Characters mapped to ``None`` are\n deleted.\n\n You can use ``str.maketrans()`` to create a translation map from\n character-to-character mappings in different formats.\n\n Note: An even more flexible approach is to create a custom character\n mapping codec using the ``codecs`` module (see\n ``encodings.cp1251`` for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that ``str.upper().isupper()`` might\n be ``False`` if ``s`` contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to ``len(s)``.\n', - 'strings': '\nString and Bytes literals\n*************************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "R" | "U"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'" | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | stringescapeseq\n longstringitem ::= longstringchar | stringescapeseq\n shortstringchar ::= \n longstringchar ::= \n stringescapeseq ::= "\\" \n\n bytesliteral ::= bytesprefix(shortbytes | longbytes)\n bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"\n shortbytes ::= "\'" shortbytesitem* "\'" | \'"\' shortbytesitem* \'"\'\n longbytes ::= "\'\'\'" longbytesitem* "\'\'\'" | \'"""\' longbytesitem* \'"""\'\n shortbytesitem ::= shortbyteschar | bytesescapeseq\n longbytesitem ::= longbyteschar | bytesescapeseq\n shortbyteschar ::= \n longbyteschar ::= \n bytesescapeseq ::= "\\" \n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the ``stringprefix`` or\n``bytesprefix`` and the rest of the literal. The source character set\nis defined by the encoding declaration; it is UTF-8 if no encoding\ndeclaration is given in the source file; see section *Encoding\ndeclarations*.\n\nIn plain English: Both types of literals can be enclosed in matching\nsingle quotes (``\'``) or double quotes (``"``). They can also be\nenclosed in matching groups of three single or double quotes (these\nare generally referred to as *triple-quoted strings*). The backslash\n(``\\``) character is used to escape characters that otherwise have a\nspecial meaning, such as newline, backslash itself, or the quote\ncharacter.\n\nBytes literals are always prefixed with ``\'b\'`` or ``\'B\'``; they\nproduce an instance of the ``bytes`` type instead of the ``str`` type.\nThey may only contain ASCII characters; bytes with a numeric value of\n128 or greater must be expressed with escapes.\n\nAs of Python 3.3 it is possible again to prefix unicode strings with a\n``u`` prefix to simplify maintenance of dual 2.x and 3.x codebases.\n\nBoth string and bytes literals may optionally be prefixed with a\nletter ``\'r\'`` or ``\'R\'``; such strings are called *raw strings* and\ntreat backslashes as literal characters. As a result, in string\nliterals, ``\'\\U\'`` and ``\'\\u\'`` escapes in raw strings are not treated\nspecially. Given that Python 2.x\'s raw unicode literals behave\ndifferently than Python 3.x\'s the ``\'ur\'`` syntax is not supported.\n\n New in version 3.3: The ``\'rb\'`` prefix of raw bytes literals has\n been added as a synonym of ``\'br\'``.\n\n New in version 3.3: Support for the unicode legacy literal\n (``u\'value\'``) was reintroduced to simplify the maintenance of dual\n Python 2.x and 3.x codebases. See **PEP 414** for more information.\n\nIn triple-quoted strings, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the string. (A "quote" is the character used to open the\nstring, i.e. either ``\'`` or ``"``.)\n\nUnless an ``\'r\'`` or ``\'R\'`` prefix is present, escape sequences in\nstrings are interpreted according to rules similar to those used by\nStandard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| ``\\newline`` | Backslash and newline ignored | |\n+-------------------+-----------------------------------+---------+\n| ``\\\\`` | Backslash (``\\``) | |\n+-------------------+-----------------------------------+---------+\n| ``\\\'`` | Single quote (``\'``) | |\n+-------------------+-----------------------------------+---------+\n| ``\\"`` | Double quote (``"``) | |\n+-------------------+-----------------------------------+---------+\n| ``\\a`` | ASCII Bell (BEL) | |\n+-------------------+-----------------------------------+---------+\n| ``\\b`` | ASCII Backspace (BS) | |\n+-------------------+-----------------------------------+---------+\n| ``\\f`` | ASCII Formfeed (FF) | |\n+-------------------+-----------------------------------+---------+\n| ``\\n`` | ASCII Linefeed (LF) | |\n+-------------------+-----------------------------------+---------+\n| ``\\r`` | ASCII Carriage Return (CR) | |\n+-------------------+-----------------------------------+---------+\n| ``\\t`` | ASCII Horizontal Tab (TAB) | |\n+-------------------+-----------------------------------+---------+\n| ``\\v`` | ASCII Vertical Tab (VT) | |\n+-------------------+-----------------------------------+---------+\n| ``\\ooo`` | Character with octal value *ooo* | (1,3) |\n+-------------------+-----------------------------------+---------+\n| ``\\xhh`` | Character with hex value *hh* | (2,3) |\n+-------------------+-----------------------------------+---------+\n\nEscape sequences only recognized in string literals are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| ``\\N{name}`` | Character named *name* in the | (4) |\n| | Unicode database | |\n+-------------------+-----------------------------------+---------+\n| ``\\uxxxx`` | Character with 16-bit hex value | (5) |\n| | *xxxx* | |\n+-------------------+-----------------------------------+---------+\n| ``\\Uxxxxxxxx`` | Character with 32-bit hex value | (6) |\n| | *xxxxxxxx* | |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. As in Standard C, up to three octal digits are accepted.\n\n2. Unlike in Standard C, exactly two hex digits are required.\n\n3. In a bytes literal, hexadecimal and octal escapes denote the byte\n with the given value. In a string literal, these escapes denote a\n Unicode character with the given value.\n\n4. Changed in version 3.3: Support for name aliases [1] has been\n added.\n\n5. Individual code units which form parts of a surrogate pair can be\n encoded using this escape sequence. Exactly four hex digits are\n required.\n\n6. Any Unicode character can be encoded this way. Exactly eight hex\n digits are required.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the string*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences only recognized in string\nliterals fall into the category of unrecognized escapes for bytes\nliterals.\n\nEven in a raw string, string quotes can be escaped with a backslash,\nbut the backslash remains in the string; for example, ``r"\\""`` is a\nvalid string literal consisting of two characters: a backslash and a\ndouble quote; ``r"\\"`` is not a valid string literal (even a raw\nstring cannot end in an odd number of backslashes). Specifically, *a\nraw string cannot end in a single backslash* (since the backslash\nwould escape the following quote character). Note also that a single\nbackslash followed by a newline is interpreted as those two characters\nas part of the string, *not* as a line continuation.\n', - 'subscriptions': '\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object that supports subscription,\ne.g. a list or dictionary. User-defined objects can support\nsubscription by defining a ``__getitem__()`` method.\n\nFor built-in objects, there are two types of objects that support\nsubscription:\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to\nan integer or a slice (as discussed in the following section).\n\nThe formal syntax makes no special provision for negative indices in\nsequences; however, built-in sequences all provide a ``__getitem__()``\nmethod that interprets negative indices by adding the length of the\nsequence to the index (so that ``x[-1]`` selects the last item of\n``x``). The resulting value must be a nonnegative integer less than\nthe number of items in the sequence, and the subscription selects the\nitem whose index is that value (counting from zero). Since the support\nfor negative indices and slicing occurs in the object\'s\n``__getitem__()`` method, subclasses overriding this method will need\nto explicitly add that support.\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n', - 'truth': "\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an ``if`` or\n``while`` condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* ``None``\n\n* ``False``\n\n* zero of any numeric type, for example, ``0``, ``0.0``, ``0j``.\n\n* any empty sequence, for example, ``''``, ``()``, ``[]``.\n\n* any empty mapping, for example, ``{}``.\n\n* instances of user-defined classes, if the class defines a\n ``__bool__()`` or ``__len__()`` method, when that method returns the\n integer zero or ``bool`` value ``False``. [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn ``0`` or ``False`` for false and ``1`` or ``True`` for true,\nunless otherwise stated. (Important exception: the Boolean operations\n``or`` and ``and`` always return one of their operands.)\n", - 'try': '\nThe ``try`` statement\n*********************\n\nThe ``try`` statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" target]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe ``except`` clause(s) specify one or more exception handlers. When\nno exception occurs in the ``try`` clause, no exception handler is\nexecuted. When an exception occurs in the ``try`` suite, a search for\nan exception handler is started. This search inspects the except\nclauses in turn until one is found that matches the exception. An\nexpression-less except clause, if present, must be last; it matches\nany exception. For an except clause with an expression, that\nexpression is evaluated, and the clause matches the exception if the\nresulting object is "compatible" with the exception. An object is\ncompatible with an exception if it is the class or a base class of the\nexception object or a tuple containing an item compatible with the\nexception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire ``try`` statement\nraised the exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the ``as`` keyword in that except clause,\nif present, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using ``as target``, it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the ``sys`` module and can be access via\n``sys.exc_info()``. ``sys.exc_info()`` returns a 3-tuple consisting of\nthe exception class, the exception instance and a traceback object\n(see section *The standard type hierarchy*) identifying the point in\nthe program where the exception occurred. ``sys.exc_info()`` values\nare restored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional ``else`` clause is executed if and when control flows off\nthe end of the ``try`` clause. [2] Exceptions in the ``else`` clause\nare not handled by the preceding ``except`` clauses.\n\nIf ``finally`` is present, it specifies a \'cleanup\' handler. The\n``try`` clause is executed, including any ``except`` and ``else``\nclauses. If an exception occurs in any of the clauses and is not\nhandled, the exception is temporarily saved. The ``finally`` clause is\nexecuted. If there is a saved exception it is re-raised at the end of\nthe ``finally`` clause. If the ``finally`` clause raises another\nexception, the saved exception is set as the context of the new\nexception. If the ``finally`` clause executes a ``return`` or\n``break`` statement, the saved exception is discarded:\n\n def f():\n try:\n 1/0\n finally:\n return 42\n\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the ``finally`` clause.\n\nWhen a ``return``, ``break`` or ``continue`` statement is executed in\nthe ``try`` suite of a ``try``...``finally`` statement, the\n``finally`` clause is also executed \'on the way out.\' A ``continue``\nstatement is illegal in the ``finally`` clause. (The reason is a\nproblem with the current implementation --- this restriction may be\nlifted in the future).\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the ``raise`` statement to\ngenerate exceptions may be found in section *The raise statement*.\n', - 'types': '\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.), although such additions\nwill often be provided via the standard library instead.\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name ``None``.\n It is used to signify the absence of a value in many situations,\n e.g., it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n ``NotImplemented``. Numeric methods and rich comparison methods may\n return this value if they do not implement the operation for the\n operands provided. (The interpreter will then try the reflected\n operation, or some other fallback, depending on the operator.) Its\n truth value is true.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the literal ``...`` or the\n built-in name ``Ellipsis``. Its truth value is true.\n\n``numbers.Number``\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n ``numbers.Integral``\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are two types of integers:\n\n Integers (``int``)\n\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans (``bool``)\n These represent the truth values False and True. The two\n objects representing the values False and True are the only\n Boolean objects. The Boolean type is a subtype of the integer\n type, and Boolean values behave like the values 0 and 1,\n respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ``"False"`` or\n ``"True"`` are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers.\n\n ``numbers.Real`` (``float``)\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these is\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n ``numbers.Complex`` (``complex``)\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number ``z`` can be retrieved through the read-only\n attributes ``z.real`` and ``z.imag``.\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function ``len()`` returns the number of\n items of a sequence. When the length of a sequence is *n*, the\n index set contains the numbers 0, 1, ..., *n*-1. Item *i* of\n sequence *a* is selected by ``a[i]``.\n\n Sequences also support slicing: ``a[i:j]`` selects all items with\n index *k* such that *i* ``<=`` *k* ``<`` *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: ``a[i:j:k]`` selects all items of *a* with index *x*\n where ``x = i + n*k``, *n* ``>=`` ``0`` and *i* ``<=`` *x* ``<``\n *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n A string is a sequence of values that represent Unicode\n codepoints. All the codepoints in range ``U+0000 - U+10FFFF``\n can be represented in a string. Python doesn\'t have a\n ``chr`` type, and every character in the string is\n represented as a string object with length ``1``. The built-\n in function ``ord()`` converts a character to its codepoint\n (as an integer); ``chr()`` converts an integer in range ``0 -\n 10FFFF`` to the corresponding character. ``str.encode()`` can\n be used to convert a ``str`` to ``bytes`` using the given\n encoding, and ``bytes.decode()`` can be used to achieve the\n opposite.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Bytes\n A bytes object is an immutable array. The items are 8-bit\n bytes, represented by integers in the range 0 <= x < 256.\n Bytes literals (like ``b\'abc\'``) and the built-in function\n ``bytes()`` can be used to construct bytes objects. Also,\n bytes objects can be decoded to strings via the ``decode()``\n method.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and ``del`` (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in ``bytearray()`` constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module ``array`` provides an additional example of\n a mutable sequence type, as does the ``collections`` module.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function ``len()``\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., ``1`` and\n ``1.0``), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n ``set()`` constructor and can be modified afterwards by several\n methods, such as ``add()``.\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in ``frozenset()`` constructor. As a frozenset is\n immutable and *hashable*, it can be used again as an element of\n another set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation ``a[k]`` selects the item indexed by\n ``k`` from the mapping ``a``; this can be used in expressions and\n as the target of assignments or ``del`` statements. The built-in\n function ``len()`` returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., ``1`` and\n ``1.0``) then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the ``{...}``\n notation (see section *Dictionary displays*).\n\n The extension modules ``dbm.ndbm`` and ``dbm.gnu`` provide\n additional examples of mapping types, as does the\n ``collections`` module.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +---------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +===========================+=================================+=============+\n | ``__doc__`` | The function\'s documentation | Writable |\n | | string, or ``None`` if | |\n | | unavailable | |\n +---------------------------+---------------------------------+-------------+\n | ``__name__`` | The function\'s name | Writable |\n +---------------------------+---------------------------------+-------------+\n | ``__qualname__`` | The function\'s *qualified name* | Writable |\n | | New in version 3.3. | |\n +---------------------------+---------------------------------+-------------+\n | ``__module__`` | The name of the module the | Writable |\n | | function was defined in, or | |\n | | ``None`` if unavailable. | |\n +---------------------------+---------------------------------+-------------+\n | ``__defaults__`` | A tuple containing default | Writable |\n | | argument values for those | |\n | | arguments that have defaults, | |\n | | or ``None`` if no arguments | |\n | | have a default value | |\n +---------------------------+---------------------------------+-------------+\n | ``__code__`` | The code object representing | Writable |\n | | the compiled function body. | |\n +---------------------------+---------------------------------+-------------+\n | ``__globals__`` | A reference to the dictionary | Read-only |\n | | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +---------------------------+---------------------------------+-------------+\n | ``__dict__`` | The namespace supporting | Writable |\n | | arbitrary function attributes. | |\n +---------------------------+---------------------------------+-------------+\n | ``__closure__`` | ``None`` or a tuple of cells | Read-only |\n | | that contain bindings for the | |\n | | function\'s free variables. | |\n +---------------------------+---------------------------------+-------------+\n | ``__annotations__`` | A dict containing annotations | Writable |\n | | of parameters. The keys of the | |\n | | dict are the parameter names, | |\n | | or ``\'return\'`` for the return | |\n | | annotation, if provided. | |\n +---------------------------+---------------------------------+-------------+\n | ``__kwdefaults__`` | A dict containing defaults for | Writable |\n | | keyword-only parameters. | |\n +---------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n Instance methods\n An instance method object combines a class, a class instance and\n any callable object (normally a user-defined function).\n\n Special read-only attributes: ``__self__`` is the class instance\n object, ``__func__`` is the function object; ``__doc__`` is the\n method\'s documentation (same as ``__func__.__doc__``);\n ``__name__`` is the method name (same as ``__func__.__name__``);\n ``__module__`` is the name of the module the method was defined\n in, or ``None`` if unavailable.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object or a class\n method object.\n\n When an instance method object is created by retrieving a user-\n defined function object from a class via one of its instances,\n its ``__self__`` attribute is the instance, and the method\n object is said to be bound. The new method\'s ``__func__``\n attribute is the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the ``__func__``\n attribute of the new instance is not the original method object\n but its ``__func__`` attribute.\n\n When an instance method object is created by retrieving a class\n method object from a class or instance, its ``__self__``\n attribute is the class itself, and its ``__func__`` attribute is\n the function object underlying the class method.\n\n When an instance method object is called, the underlying\n function (``__func__``) is called, inserting the class instance\n (``__self__``) in front of the argument list. For instance,\n when ``C`` is a class which contains a definition for a function\n ``f()``, and ``x`` is an instance of ``C``, calling ``x.f(1)``\n is equivalent to calling ``C.f(x, 1)``.\n\n When an instance method object is derived from a class method\n object, the "class instance" stored in ``__self__`` will\n actually be the class itself, so that calling either ``x.f(1)``\n or ``C.f(1)`` is equivalent to calling ``f(C,1)`` where ``f`` is\n the underlying function.\n\n Note that the transformation from function object to instance\n method object happens each time the attribute is retrieved from\n the instance. In some cases, a fruitful optimization is to\n assign the attribute to a local variable and call that local\n variable. Also notice that this transformation only happens for\n user-defined functions; other callable objects (and all non-\n callable objects) are retrieved without transformation. It is\n also important to note that user-defined functions which are\n attributes of a class instance are not converted to bound\n methods; this *only* happens when the function is an attribute\n of the class.\n\n Generator functions\n A function or method which uses the ``yield`` statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s ``iterator.__next__()`` method will cause the\n function to execute until it provides a value using the\n ``yield`` statement. When the function executes a ``return``\n statement or falls off the end, a ``StopIteration`` exception is\n raised and the iterator will have reached the end of the set of\n values to be returned.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are ``len()`` and ``math.sin()``\n (``math`` is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: ``__doc__`` is the function\'s documentation\n string, or ``None`` if unavailable; ``__name__`` is the\n function\'s name; ``__self__`` is set to ``None`` (but see the\n next item); ``__module__`` is the name of the module the\n function was defined in or ``None`` if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n ``alist.append()``, assuming *alist* is a list object. In this\n case, the special read-only attribute ``__self__`` is set to the\n object denoted by *alist*.\n\n Classes\n Classes are callable. These objects normally act as factories\n for new instances of themselves, but variations are possible for\n class types that override ``__new__()``. The arguments of the\n call are passed to ``__new__()`` and, in the typical case, to\n ``__init__()`` to initialize the new instance.\n\n Class Instances\n Instances of arbitrary classes can be made callable by defining\n a ``__call__()`` method in their class.\n\nModules\n Modules are a basic organizational unit of Python code, and are\n created by the *import system* as invoked either by the ``import``\n statement (see ``import``), or by calling functions such as\n ``importlib.import_module()`` and built-in ``__import__()``. A\n module object has a namespace implemented by a dictionary object\n (this is the dictionary referenced by the ``__globals__`` attribute\n of functions defined in the module). Attribute references are\n translated to lookups in this dictionary, e.g., ``m.x`` is\n equivalent to ``m.__dict__["x"]``. A module object does not contain\n the code object used to initialize the module (since it isn\'t\n needed once the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., ``m.x = 1`` is equivalent to ``m.__dict__["x"] = 1``.\n\n Special read-only attribute: ``__dict__`` is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: ``__name__`` is the module\'s\n name; ``__doc__`` is the module\'s documentation string, or ``None``\n if unavailable; ``__file__`` is the pathname of the file from which\n the module was loaded, if it was loaded from a file. The\n ``__file__`` attribute may be missing for certain types of modules,\n such as C modules that are statically linked into the interpreter;\n for extension modules loaded dynamically from a shared library, it\n is the pathname of the shared library file.\n\nCustom classes\n Custom class types are typically created by class definitions (see\n section *Class definitions*). A class has a namespace implemented\n by a dictionary object. Class attribute references are translated\n to lookups in this dictionary, e.g., ``C.x`` is translated to\n ``C.__dict__["x"]`` (although there are a number of hooks which\n allow for other means of locating attributes). When the attribute\n name is not found there, the attribute search continues in the base\n classes. This search of the base classes uses the C3 method\n resolution order which behaves correctly even in the presence of\n \'diamond\' inheritance structures where there are multiple\n inheritance paths leading back to a common ancestor. Additional\n details on the C3 MRO used by Python can be found in the\n documentation accompanying the 2.3 release at\n http://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class ``C``, say) would yield\n a class method object, it is transformed into an instance method\n object whose ``__self__`` attributes is ``C``. When it would yield\n a static method object, it is transformed into the object wrapped\n by the static method object. See section *Implementing Descriptors*\n for another way in which attributes retrieved from a class may\n differ from those actually contained in its ``__dict__``.\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: ``__name__`` is the class name; ``__module__``\n is the module name in which the class was defined; ``__dict__`` is\n the dictionary containing the class\'s namespace; ``__bases__`` is a\n tuple (possibly empty or a singleton) containing the base classes,\n in the order of their occurrence in the base class list;\n ``__doc__`` is the class\'s documentation string, or None if\n undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object, it is transformed into an instance method object\n whose ``__self__`` attribute is the instance. Static method and\n class method objects are also transformed; see above under\n "Classes". See section *Implementing Descriptors* for another way\n in which attributes of a class retrieved via its instances may\n differ from the objects actually stored in the class\'s\n ``__dict__``. If no class attribute is found, and the object\'s\n class has a ``__getattr__()`` method, that is called to satisfy the\n lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n ``__setattr__()`` or ``__delattr__()`` method, this is called\n instead of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: ``__dict__`` is the attribute dictionary;\n ``__class__`` is the instance\'s class.\n\nI/O objects (also known as file objects)\n A *file object* represents an open file. Various shortcuts are\n available to create file objects: the ``open()`` built-in function,\n and also ``os.popen()``, ``os.fdopen()``, and the ``makefile()``\n method of socket objects (and perhaps by other functions or methods\n provided by extension modules).\n\n The objects ``sys.stdin``, ``sys.stdout`` and ``sys.stderr`` are\n initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams; they are all open in text\n mode and therefore follow the interface defined by the\n ``io.TextIOBase`` abstract class.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: ``co_name`` gives the function\n name; ``co_argcount`` is the number of positional arguments\n (including arguments with default values); ``co_nlocals`` is the\n number of local variables used by the function (including\n arguments); ``co_varnames`` is a tuple containing the names of\n the local variables (starting with the argument names);\n ``co_cellvars`` is a tuple containing the names of local\n variables that are referenced by nested functions;\n ``co_freevars`` is a tuple containing the names of free\n variables; ``co_code`` is a string representing the sequence of\n bytecode instructions; ``co_consts`` is a tuple containing the\n literals used by the bytecode; ``co_names`` is a tuple\n containing the names used by the bytecode; ``co_filename`` is\n the filename from which the code was compiled;\n ``co_firstlineno`` is the first line number of the function;\n ``co_lnotab`` is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); ``co_stacksize`` is the required stack size\n (including local variables); ``co_flags`` is an integer encoding\n a number of flags for the interpreter.\n\n The following flag bits are defined for ``co_flags``: bit\n ``0x04`` is set if the function uses the ``*arguments`` syntax\n to accept an arbitrary number of positional arguments; bit\n ``0x08`` is set if the function uses the ``**keywords`` syntax\n to accept arbitrary keyword arguments; bit ``0x20`` is set if\n the function is a generator.\n\n Future feature declarations (``from __future__ import\n division``) also use bits in ``co_flags`` to indicate whether a\n code object was compiled with a particular feature enabled: bit\n ``0x2000`` is set if the function was compiled with future\n division enabled; bits ``0x10`` and ``0x1000`` were used in\n earlier versions of Python.\n\n Other bits in ``co_flags`` are reserved for internal use.\n\n If a code object represents a function, the first item in\n ``co_consts`` is the documentation string of the function, or\n ``None`` if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: ``f_back`` is to the previous\n stack frame (towards the caller), or ``None`` if this is the\n bottom stack frame; ``f_code`` is the code object being executed\n in this frame; ``f_locals`` is the dictionary used to look up\n local variables; ``f_globals`` is used for global variables;\n ``f_builtins`` is used for built-in (intrinsic) names;\n ``f_lasti`` gives the precise instruction (this is an index into\n the bytecode string of the code object).\n\n Special writable attributes: ``f_trace``, if not ``None``, is a\n function called at the start of each source code line (this is\n used by the debugger); ``f_lineno`` is the current line number\n of the frame --- writing to this from within a trace function\n jumps to the given line (only for the bottom-most frame). A\n debugger can implement a Jump command (aka Set Next Statement)\n by writing to f_lineno.\n\n Traceback objects\n Traceback objects represent a stack trace of an exception. A\n traceback object is created when an exception occurs. When the\n search for an exception handler unwinds the execution stack, at\n each unwound level a traceback object is inserted in front of\n the current traceback. When an exception handler is entered,\n the stack trace is made available to the program. (See section\n *The try statement*.) It is accessible as the third item of the\n tuple returned by ``sys.exc_info()``. When the program contains\n no suitable handler, the stack trace is written (nicely\n formatted) to the standard error stream; if the interpreter is\n interactive, it is also made available to the user as\n ``sys.last_traceback``.\n\n Special read-only attributes: ``tb_next`` is the next level in\n the stack trace (towards the frame where the exception\n occurred), or ``None`` if there is no next level; ``tb_frame``\n points to the execution frame of the current level;\n ``tb_lineno`` gives the line number where the exception\n occurred; ``tb_lasti`` indicates the precise instruction. The\n line number and last instruction in the traceback may differ\n from the line number of its frame object if the exception\n occurred in a ``try`` statement with no matching except clause\n or with a finally clause.\n\n Slice objects\n Slice objects are used to represent slices for ``__getitem__()``\n methods. They are also created by the built-in ``slice()``\n function.\n\n Special read-only attributes: ``start`` is the lower bound;\n ``stop`` is the upper bound; ``step`` is the step value; each is\n ``None`` if omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the slice that the slice object\n would describe if applied to a sequence of *length* items.\n It returns a tuple of three integers; respectively these are\n the *start* and *stop* indices and the *step* or stride\n length of the slice. Missing or out-of-bounds indices are\n handled in a manner consistent with regular slices.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n ``staticmethod()`` constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in ``classmethod()`` constructor.\n', - 'typesfunctions': '\nFunctions\n*********\n\nFunction objects are created by function definitions. The only\noperation on a function object is to call it: ``func(argument-list)``.\n\nThere are really two flavors of function objects: built-in functions\nand user-defined functions. Both support the same operation (to call\nthe function), but the implementation is different, hence the\ndifferent object types.\n\nSee *Function definitions* for more information.\n', - 'typesmapping': '\nMapping Types --- ``dict``\n**************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built-\nin ``list``, ``set``, and ``tuple`` classes, and the ``collections``\nmodule.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as ``1`` and ``1.0``) then they can be used interchangeably to\nindex the same dictionary entry. (Note however, that since computers\nstore floating-point numbers as approximations it is usually unwise to\nuse them as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of\n``key: value`` pairs within braces, for example: ``{\'jack\': 4098,\n\'sjoerd\': 4127}`` or ``{4098: \'jack\', 4127: \'sjoerd\'}``, or by the\n``dict`` constructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterator*\n object. Each item in the iterable must itself be an iterator with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to ``{"one": 1, "two": 2, "three": 3}``:\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a ``KeyError`` if\n *key* is not in the map.\n\n If a subclass of dict defines a method ``__missing__()``, if the\n key *key* is not present, the ``d[key]`` operation calls that\n method with the key *key* as argument. The ``d[key]`` operation\n then returns or raises whatever is returned or raised by the\n ``__missing__(key)`` call if the key is not present. No other\n operations or methods invoke ``__missing__()``. If\n ``__missing__()`` is not defined, ``KeyError`` is raised.\n ``__missing__()`` must be a method; it cannot be an instance\n variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n See ``collections.Counter`` for a complete implementation\n including other methods helpful for accumulating and managing\n tallies.\n\n d[key] = value\n\n Set ``d[key]`` to *value*.\n\n del d[key]\n\n Remove ``d[key]`` from *d*. Raises a ``KeyError`` if *key* is\n not in the map.\n\n key in d\n\n Return ``True`` if *d* has a key *key*, else ``False``.\n\n key not in d\n\n Equivalent to ``not key in d``.\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for ``iter(d.keys())``.\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n classmethod fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n ``fromkeys()`` is a class method that returns a new dictionary.\n *value* defaults to ``None``.\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to ``None``,\n so that this method never raises a ``KeyError``.\n\n items()\n\n Return a new view of the dictionary\'s items (``(key, value)``\n pairs). See the *documentation of view objects*.\n\n keys()\n\n Return a new view of the dictionary\'s keys. See the\n *documentation of view objects*.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a ``KeyError`` is raised.\n\n popitem()\n\n Remove and return an arbitrary ``(key, value)`` pair from the\n dictionary.\n\n ``popitem()`` is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling ``popitem()`` raises a ``KeyError``.\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to ``None``.\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return ``None``.\n\n ``update()`` accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: ``d.update(red=1,\n blue=2)``.\n\n values()\n\n Return a new view of the dictionary\'s values. See the\n *documentation of view objects*.\n\nSee also:\n\n ``types.MappingProxyType`` can be used to create a read-only view\n of a ``dict``.\n\n\nDictionary view objects\n=======================\n\nThe objects returned by ``dict.keys()``, ``dict.values()`` and\n``dict.items()`` are *view objects*. They provide a dynamic view on\nthe dictionary\'s entries, which means that when the dictionary\nchanges, the view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of ``(key, value)``) in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of ``(value, key)`` pairs\n using ``zip()``: ``pairs = zip(d.values(), d.keys())``. Another\n way to create the same list is ``pairs = [(v, k) for (k, v) in\n d.items()]``.\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a ``RuntimeError`` or fail to iterate over all entries.\n\nx in dictview\n\n Return ``True`` if *x* is in the underlying dictionary\'s keys,\n values or items (in the latter case, *x* should be a ``(key,\n value)`` tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that ``(key, value)`` pairs are unique\nand hashable, then the items view is also set-like. (Values views are\nnot treated as set-like since the entries are generally not unique.)\nFor set-like views, all of the operations defined for the abstract\nbase class ``collections.abc.Set`` are available (for example, ``==``,\n``<``, or ``^``).\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.keys()\n >>> values = dishes.values()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n >>> keys ^ {\'sausage\', \'juice\'}\n {\'juice\', \'sausage\', \'bacon\', \'spam\'}\n', - 'typesmethods': '\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as ``append()`` on\nlists) and class instance methods. Built-in methods are described\nwith the types that support them.\n\nIf you access a method (a function defined in a class namespace)\nthrough an instance, you get a special object: a *bound method* (also\ncalled *instance method*) object. When called, it will add the\n``self`` argument to the argument list. Bound methods have two\nspecial read-only attributes: ``m.__self__`` is the object on which\nthe method operates, and ``m.__func__`` is the function implementing\nthe method. Calling ``m(arg-1, arg-2, ..., arg-n)`` is completely\nequivalent to calling ``m.__func__(m.__self__, arg-1, arg-2, ...,\narg-n)``.\n\nLike function objects, bound method objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object (``meth.__func__``), setting method\nattributes on bound methods is disallowed. Attempting to set an\nattribute on a method results in an ``AttributeError`` being raised.\nIn order to set a method attribute, you need to explicitly set it on\nthe underlying function object:\n\n >>> class C:\n ... def method(self):\n ... pass\n ...\n >>> c = C()\n >>> c.method.whoami = \'my name is method\' # can\'t set on the method\n Traceback (most recent call last):\n File "", line 1, in \n AttributeError: \'method\' object has no attribute \'whoami\'\n >>> c.method.__func__.whoami = \'my name is method\'\n >>> c.method.whoami\n \'my name is method\'\n\nSee *The standard type hierarchy* for more information.\n', - 'typesmodules': "\nModules\n*******\n\nThe only special operation on a module is attribute access:\n``m.name``, where *m* is a module and *name* accesses a name defined\nin *m*'s symbol table. Module attributes can be assigned to. (Note\nthat the ``import`` statement is not, strictly speaking, an operation\non a module object; ``import foo`` does not require a module object\nnamed *foo* to exist, rather it requires an (external) *definition*\nfor a module named *foo* somewhere.)\n\nA special attribute of every module is ``__dict__``. This is the\ndictionary containing the module's symbol table. Modifying this\ndictionary will actually change the module's symbol table, but direct\nassignment to the ``__dict__`` attribute is not possible (you can\nwrite ``m.__dict__['a'] = 1``, which defines ``m.a`` to be ``1``, but\nyou can't write ``m.__dict__ = {}``). Modifying ``__dict__`` directly\nis not recommended.\n\nModules built into the interpreter are written like this: ````. If loaded from a file, they are written as\n````.\n", - 'typesseq': '\nSequence Types --- ``list``, ``tuple``, ``range``\n*************************************************\n\nThere are three basic sequence types: lists, tuples, and range\nobjects. Additional sequence types tailored for processing of *binary\ndata* and *text strings* are described in dedicated sections.\n\n\nCommon Sequence Operations\n==========================\n\nThe operations in the following table are supported by most sequence\ntypes, both mutable and immutable. The ``collections.abc.Sequence``\nABC is provided to make it easier to correctly implement these\noperations on custom sequence types.\n\nThis table lists the sequence operations sorted in ascending priority\n(operations in the same box have the same priority). In the table,\n*s* and *t* are sequences of the same type, *n*, *i*, *j* and *k* are\nintegers and *x* is an arbitrary object that meets any type and value\nrestrictions imposed by *s*.\n\nThe ``in`` and ``not in`` operations have the same priorities as the\ncomparison operations. The ``+`` (concatenation) and ``*``\n(repetition) operations have the same priority as the corresponding\nnumeric operations.\n\n+----------------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+============================+==================================+============+\n| ``x in s`` | ``True`` if an item of *s* is | (1) |\n| | equal to *x*, else ``False`` | |\n+----------------------------+----------------------------------+------------+\n| ``x not in s`` | ``False`` if an item of *s* is | (1) |\n| | equal to *x*, else ``True`` | |\n+----------------------------+----------------------------------+------------+\n| ``s + t`` | the concatenation of *s* and *t* | (6)(7) |\n+----------------------------+----------------------------------+------------+\n| ``s * n`` or ``n * s`` | *n* shallow copies of *s* | (2)(7) |\n| | concatenated | |\n+----------------------------+----------------------------------+------------+\n| ``s[i]`` | *i*th item of *s*, origin 0 | (3) |\n+----------------------------+----------------------------------+------------+\n| ``s[i:j]`` | slice of *s* from *i* to *j* | (3)(4) |\n+----------------------------+----------------------------------+------------+\n| ``s[i:j:k]`` | slice of *s* from *i* to *j* | (3)(5) |\n| | with step *k* | |\n+----------------------------+----------------------------------+------------+\n| ``len(s)`` | length of *s* | |\n+----------------------------+----------------------------------+------------+\n| ``min(s)`` | smallest item of *s* | |\n+----------------------------+----------------------------------+------------+\n| ``max(s)`` | largest item of *s* | |\n+----------------------------+----------------------------------+------------+\n| ``s.index(x[, i[, j]])`` | index of the first occurrence of | (8) |\n| | *x* in *s* (at or after index | |\n| | *i* and before index *j*) | |\n+----------------------------+----------------------------------+------------+\n| ``s.count(x)`` | total number of occurrences of | |\n| | *x* in *s* | |\n+----------------------------+----------------------------------+------------+\n\nSequences of the same type also support comparisons. In particular,\ntuples and lists are compared lexicographically by comparing\ncorresponding elements. This means that to compare equal, every\nelement must compare equal and the two sequences must be of the same\ntype and have the same length. (For full details see *Comparisons* in\nthe language reference.)\n\nNotes:\n\n1. While the ``in`` and ``not in`` operations are used only for simple\n containment testing in the general case, some specialised sequences\n (such as ``str``, ``bytes`` and ``bytearray``) also use them for\n subsequence testing:\n\n >>> "gg" in "eggs"\n True\n\n2. Values of *n* less than ``0`` are treated as ``0`` (which yields an\n empty sequence of the same type as *s*). Note also that the copies\n are shallow; nested structures are not copied. This often haunts\n new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that ``[[]]`` is a one-element list containing\n an empty list, so all three elements of ``[[]] * 3`` are (pointers\n to) this single empty list. Modifying any of the elements of\n ``lists`` modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n3. If *i* or *j* is negative, the index is relative to the end of the\n string: ``len(s) + i`` or ``len(s) + j`` is substituted. But note\n that ``-0`` is still ``0``.\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that ``i <= k < j``. If *i* or *j* is\n greater than ``len(s)``, use ``len(s)``. If *i* is omitted or\n ``None``, use ``0``. If *j* is omitted or ``None``, use\n ``len(s)``. If *i* is greater than or equal to *j*, the slice is\n empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index ``x = i + n*k`` such that ``0 <= n <\n (j-i)/k``. In other words, the indices are ``i``, ``i+k``,\n ``i+2*k``, ``i+3*k`` and so on, stopping when *j* is reached (but\n never including *j*). If *i* or *j* is greater than ``len(s)``,\n use ``len(s)``. If *i* or *j* are omitted or ``None``, they become\n "end" values (which end depends on the sign of *k*). Note, *k*\n cannot be zero. If *k* is ``None``, it is treated like ``1``.\n\n6. Concatenating immutable sequences always results in a new object.\n This means that building up a sequence by repeated concatenation\n will have a quadratic runtime cost in the total sequence length.\n To get a linear runtime cost, you must switch to one of the\n alternatives below:\n\n * if concatenating ``str`` objects, you can build a list and use\n ``str.join()`` at the end or else write to a ``io.StringIO``\n instance and retrieve its value when complete\n\n * if concatenating ``bytes`` objects, you can similarly use\n ``bytes.join()`` or ``io.BytesIO``, or you can do in-place\n concatenation with a ``bytearray`` object. ``bytearray`` objects\n are mutable and have an efficient overallocation mechanism\n\n * if concatenating ``tuple`` objects, extend a ``list`` instead\n\n * for other types, investigate the relevant class documentation\n\n7. Some sequence types (such as ``range``) only support item sequences\n that follow specific patterns, and hence don\'t support sequence\n concatenation or repetition.\n\n8. ``index`` raises ``ValueError`` when *x* is not found in *s*. When\n supported, the additional arguments to the index method allow\n efficient searching of subsections of the sequence. Passing the\n extra arguments is roughly equivalent to using ``s[i:j].index(x)``,\n only without copying any data and with the returned index being\n relative to the start of the sequence rather than the start of the\n slice.\n\n\nImmutable Sequence Types\n========================\n\nThe only operation that immutable sequence types generally implement\nthat is not also implemented by mutable sequence types is support for\nthe ``hash()`` built-in.\n\nThis support allows immutable sequences, such as ``tuple`` instances,\nto be used as ``dict`` keys and stored in ``set`` and ``frozenset``\ninstances.\n\nAttempting to hash an immutable sequence that contains unhashable\nvalues will result in ``TypeError``.\n\n\nMutable Sequence Types\n======================\n\nThe operations in the following table are defined on mutable sequence\ntypes. The ``collections.abc.MutableSequence`` ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, ``bytearray`` only\naccepts integers that meet the value restriction ``0 <= x <= 255``).\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | appends *x* to the end of the | |\n| | sequence (same as | |\n| | ``s[len(s):len(s)] = [x]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.clear()`` | removes all items from ``s`` | (5) |\n| | (same as ``del s[:]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.copy()`` | creates a shallow copy of ``s`` | (5) |\n| | (same as ``s[:]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(t)`` | extends *s* with the contents of | |\n| | *t* (same as ``s[len(s):len(s)] | |\n| | = t``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | inserts *x* into *s* at the | |\n| | index given by *i* (same as | |\n| | ``s[i:i] = [x]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | retrieves the item at *i* and | (2) |\n| | also removes it from *s* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | remove the first item from *s* | (3) |\n| | where ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (4) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to ``-1``, so that by default\n the last item is removed and returned.\n\n3. ``remove`` raises ``ValueError`` when *x* is not found in *s*.\n\n4. The ``reverse()`` method modifies the sequence in place for economy\n of space when reversing a large sequence. To remind users that it\n operates by side effect, it does not return the reversed sequence.\n\n5. ``clear()`` and ``copy()`` are included for consistency with the\n interfaces of mutable containers that don\'t support slicing\n operations (such as ``dict`` and ``set``)\n\n New in version 3.3: ``clear()`` and ``copy()`` methods.\n\n\nLists\n=====\n\nLists are mutable sequences, typically used to store collections of\nhomogeneous items (where the precise degree of similarity will vary by\napplication).\n\nclass class list([iterable])\n\n Lists may be constructed in several ways:\n\n * Using a pair of square brackets to denote the empty list: ``[]``\n\n * Using square brackets, separating items with commas: ``[a]``,\n ``[a, b, c]``\n\n * Using a list comprehension: ``[x for x in iterable]``\n\n * Using the type constructor: ``list()`` or ``list(iterable)``\n\n The constructor builds a list whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a list, a copy is made and\n returned, similar to ``iterable[:]``. For example, ``list(\'abc\')``\n returns ``[\'a\', \'b\', \'c\']`` and ``list( (1, 2, 3) )`` returns ``[1,\n 2, 3]``. If no argument is given, the constructor creates a new\n empty list, ``[]``.\n\n Many other operations also produce lists, including the\n ``sorted()`` built-in.\n\n Lists implement all of the *common* and *mutable* sequence\n operations. Lists also provide the following additional method:\n\n sort(*, key=None, reverse=None)\n\n This method sorts the list in place, using only ``<``\n comparisons between items. Exceptions are not suppressed - if\n any comparison operations fail, the entire sort operation will\n fail (and the list will likely be left in a partially modified\n state).\n\n *key* specifies a function of one argument that is used to\n extract a comparison key from each list element (for example,\n ``key=str.lower``). The key corresponding to each item in the\n list is calculated once and then used for the entire sorting\n process. The default value of ``None`` means that list items are\n sorted directly without calculating a separate key value.\n\n The ``functools.cmp_to_key()`` utility is available to convert a\n 2.x style *cmp* function to a *key* function.\n\n *reverse* is a boolean value. If set to ``True``, then the list\n elements are sorted as if each comparison were reversed.\n\n This method modifies the sequence in place for economy of space\n when sorting a large sequence. To remind users that it operates\n by side effect, it does not return the sorted sequence (use\n ``sorted()`` to explicitly request a new sorted list instance).\n\n The ``sort()`` method is guaranteed to be stable. A sort is\n stable if it guarantees not to change the relative order of\n elements that compare equal --- this is helpful for sorting in\n multiple passes (for example, sort by department, then by salary\n grade).\n\n **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python makes the list appear\n empty for the duration, and raises ``ValueError`` if it can\n detect that the list has been mutated during a sort.\n\n\nTuples\n======\n\nTuples are immutable sequences, typically used to store collections of\nheterogeneous data (such as the 2-tuples produced by the\n``enumerate()`` built-in). Tuples are also used for cases where an\nimmutable sequence of homogeneous data is needed (such as allowing\nstorage in a ``set`` or ``dict`` instance).\n\nclass class tuple([iterable])\n\n Tuples may be constructed in a number of ways:\n\n * Using a pair of parentheses to denote the empty tuple: ``()``\n\n * Using a trailing comma for a singleton tuple: ``a,`` or ``(a,)``\n\n * Separating items with commas: ``a, b, c`` or ``(a, b, c)``\n\n * Using the ``tuple()`` built-in: ``tuple()`` or\n ``tuple(iterable)``\n\n The constructor builds a tuple whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a tuple, it is returned\n unchanged. For example, ``tuple(\'abc\')`` returns ``(\'a\', \'b\',\n \'c\')`` and ``tuple( [1, 2, 3] )`` returns ``(1, 2, 3)``. If no\n argument is given, the constructor creates a new empty tuple,\n ``()``.\n\n Note that it is actually the comma which makes a tuple, not the\n parentheses. The parentheses are optional, except in the empty\n tuple case, or when they are needed to avoid syntactic ambiguity.\n For example, ``f(a, b, c)`` is a function call with three\n arguments, while ``f((a, b, c))`` is a function call with a 3-tuple\n as the sole argument.\n\n Tuples implement all of the *common* sequence operations.\n\nFor heterogeneous collections of data where access by name is clearer\nthan access by index, ``collections.namedtuple()`` may be a more\nappropriate choice than a simple tuple object.\n\n\nRanges\n======\n\nThe ``range`` type represents an immutable sequence of numbers and is\ncommonly used for looping a specific number of times in ``for`` loops.\n\nclass class range(stop)\nclass class range(start, stop[, step])\n\n The arguments to the range constructor must be integers (either\n built-in ``int`` or any object that implements the ``__index__``\n special method). If the *step* argument is omitted, it defaults to\n ``1``. If the *start* argument is omitted, it defaults to ``0``. If\n *step* is zero, ``ValueError`` is raised.\n\n For a positive *step*, the contents of a range ``r`` are determined\n by the formula ``r[i] = start + step*i`` where ``i >= 0`` and\n ``r[i] < stop``.\n\n For a negative *step*, the contents of the range are still\n determined by the formula ``r[i] = start + step*i``, but the\n constraints are ``i >= 0`` and ``r[i] > stop``.\n\n A range object will be empty if ``r[0]`` does not meet the value\n constraint. Ranges do support negative indices, but these are\n interpreted as indexing from the end of the sequence determined by\n the positive indices.\n\n Ranges containing absolute values larger than ``sys.maxsize`` are\n permitted but some features (such as ``len()``) may raise\n ``OverflowError``.\n\n Range examples:\n\n >>> list(range(10))\n [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n >>> list(range(1, 11))\n [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n >>> list(range(0, 30, 5))\n [0, 5, 10, 15, 20, 25]\n >>> list(range(0, 10, 3))\n [0, 3, 6, 9]\n >>> list(range(0, -10, -1))\n [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]\n >>> list(range(0))\n []\n >>> list(range(1, 0))\n []\n\n Ranges implement all of the *common* sequence operations except\n concatenation and repetition (due to the fact that range objects\n can only represent sequences that follow a strict pattern and\n repetition and concatenation will usually violate that pattern).\n\nThe advantage of the ``range`` type over a regular ``list`` or\n``tuple`` is that a ``range`` object will always take the same (small)\namount of memory, no matter the size of the range it represents (as it\nonly stores the ``start``, ``stop`` and ``step`` values, calculating\nindividual items and subranges as needed).\n\nRange objects implement the ``collections.abc.Sequence`` ABC, and\nprovide features such as containment tests, element index lookup,\nslicing and support for negative indices (see *Sequence Types ---\nlist, tuple, range*):\n\n>>> r = range(0, 20, 2)\n>>> r\nrange(0, 20, 2)\n>>> 11 in r\nFalse\n>>> 10 in r\nTrue\n>>> r.index(10)\n5\n>>> r[5]\n10\n>>> r[:5]\nrange(0, 10, 2)\n>>> r[-1]\n18\n\nTesting range objects for equality with ``==`` and ``!=`` compares\nthem as sequences. That is, two range objects are considered equal if\nthey represent the same sequence of values. (Note that two range\nobjects that compare equal might have different ``start``, ``stop``\nand ``step`` attributes, for example ``range(0) == range(2, 1, 3)`` or\n``range(0, 3, 2) == range(0, 4, 2)``.)\n\nChanged in version 3.2: Implement the Sequence ABC. Support slicing\nand negative indices. Test ``int`` objects for membership in constant\ntime instead of iterating through all items.\n\nChanged in version 3.3: Define \'==\' and \'!=\' to compare range objects\nbased on the sequence of values they define (instead of comparing\nbased on object identity).\n\nNew in version 3.3: The ``start``, ``stop`` and ``step`` attributes.\n', - 'typesseq-mutable': "\nMutable Sequence Types\n**********************\n\nThe operations in the following table are defined on mutable sequence\ntypes. The ``collections.abc.MutableSequence`` ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, ``bytearray`` only\naccepts integers that meet the value restriction ``0 <= x <= 255``).\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | appends *x* to the end of the | |\n| | sequence (same as | |\n| | ``s[len(s):len(s)] = [x]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.clear()`` | removes all items from ``s`` | (5) |\n| | (same as ``del s[:]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.copy()`` | creates a shallow copy of ``s`` | (5) |\n| | (same as ``s[:]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(t)`` | extends *s* with the contents of | |\n| | *t* (same as ``s[len(s):len(s)] | |\n| | = t``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | inserts *x* into *s* at the | |\n| | index given by *i* (same as | |\n| | ``s[i:i] = [x]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | retrieves the item at *i* and | (2) |\n| | also removes it from *s* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | remove the first item from *s* | (3) |\n| | where ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (4) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to ``-1``, so that by default\n the last item is removed and returned.\n\n3. ``remove`` raises ``ValueError`` when *x* is not found in *s*.\n\n4. The ``reverse()`` method modifies the sequence in place for economy\n of space when reversing a large sequence. To remind users that it\n operates by side effect, it does not return the reversed sequence.\n\n5. ``clear()`` and ``copy()`` are included for consistency with the\n interfaces of mutable containers that don't support slicing\n operations (such as ``dict`` and ``set``)\n\n New in version 3.3: ``clear()`` and ``copy()`` methods.\n", - 'unary': '\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary ``-`` (minus) operator yields the negation of its numeric\nargument.\n\nThe unary ``+`` (plus) operator yields its numeric argument unchanged.\n\nThe unary ``~`` (invert) operator yields the bitwise inversion of its\ninteger argument. The bitwise inversion of ``x`` is defined as\n``-(x+1)``. It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n``TypeError`` exception is raised.\n', - 'while': '\nThe ``while`` statement\n***********************\n\nThe ``while`` statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the ``else`` clause, if present, is\nexecuted and the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ngoes back to testing the expression.\n', - 'with': '\nThe ``with`` statement\n**********************\n\nThe ``with`` statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common\n``try``...``except``...``finally`` usage patterns to be encapsulated\nfor convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the ``with`` statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the ``with_item``)\n is evaluated to obtain a context manager.\n\n2. The context manager\'s ``__exit__()`` is loaded for later use.\n\n3. The context manager\'s ``__enter__()`` method is invoked.\n\n4. If a target was included in the ``with`` statement, the return\n value from ``__enter__()`` is assigned to it.\n\n Note: The ``with`` statement guarantees that if the ``__enter__()``\n method returns without an error, then ``__exit__()`` will always\n be called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s ``__exit__()`` method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to ``__exit__()``. Otherwise,\n three ``None`` arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the ``__exit__()`` method was false, the exception is\n reraised. If the return value was true, the exception is\n suppressed, and execution continues with the statement following\n the ``with`` statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from ``__exit__()`` is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple ``with`` statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` statement.\n', - 'yield': '\nThe ``yield`` statement\n***********************\n\n yield_stmt ::= yield_expression\n\nThe ``yield`` statement is only used when defining a generator\nfunction, and is only used in the body of the generator function.\nUsing a ``yield`` statement in a function definition is sufficient to\ncause that definition to create a generator function instead of a\nnormal function.\n\nWhen a generator function is called, it returns an iterator known as a\ngenerator iterator, or more commonly, a generator. The body of the\ngenerator function is executed by calling the ``next()`` function on\nthe generator repeatedly until it raises an exception.\n\nWhen a ``yield`` statement is executed, the state of the generator is\nfrozen and the value of ``expression_list`` is returned to\n``next()``\'s caller. By "frozen" we mean that all local state is\nretained, including the current bindings of local variables, the\ninstruction pointer, and the internal evaluation stack: enough\ninformation is saved so that the next time ``next()`` is invoked, the\nfunction can proceed exactly as if the ``yield`` statement were just\nanother external call.\n\nThe ``yield`` statement is allowed in the ``try`` clause of a ``try``\n... ``finally`` construct. If the generator is not resumed before it\nis finalized (by reaching a zero reference count or by being garbage\ncollected), the generator-iterator\'s ``close()`` method will be\ncalled, allowing any pending ``finally`` clauses to execute.\n\nWhen ``yield from `` is used, it treats the supplied expression\nas a subiterator, producing values from it until the underlying\niterator is exhausted.\n\n Changed in version 3.3: Added ``yield from `` to delegate\n control flow to a subiterator\n\nFor full details of ``yield`` semantics, refer to the *Yield\nexpressions* section.\n\nSee also:\n\n **PEP 0255** - Simple Generators\n The proposal for adding generators and the ``yield`` statement\n to Python.\n\n **PEP 0342** - Coroutines via Enhanced Generators\n The proposal to enhance the API and syntax of generators, making\n them usable as simple coroutines.\n\n **PEP 0380** - Syntax for Delegating to a Subgenerator\n The proposal to introduce the ``yield_from`` syntax, making\n delegation to sub-generators easy.\n'} + 'naming': '\nNaming and binding\n******************\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal". If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, a\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\nglobal statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n=================================\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', + 'nonlocal': '\nThe "nonlocal" statement\n************************\n\n nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*\n\nThe "nonlocal" statement causes the listed identifiers to refer to\npreviously bound variables in the nearest enclosing scope. This is\nimportant because the default behavior for binding is to search the\nlocal namespace first. The statement allows encapsulated code to\nrebind variables outside of the local scope besides the global\n(module) scope.\n\nNames listed in a "nonlocal" statement, unlike to those listed in a\n"global" statement, must refer to pre-existing bindings in an\nenclosing scope (the scope in which a new binding should be created\ncannot be determined unambiguously).\n\nNames listed in a "nonlocal" statement must not collide with pre-\nexisting bindings in the local scope.\n\nSee also: **PEP 3104** - Access to Names in Outer Scopes\n\n The specification for the "nonlocal" statement.\n', + 'numbers': '\nNumeric literals\n****************\n\nThere are three types of numeric literals: integers, floating point\nnumbers, and imaginary numbers. There are no complex literals\n(complex numbers can be formed by adding a real number and an\nimaginary number).\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator \'"-"\' and the\nliteral "1".\n', + 'numeric-types': '\nEmulating numeric types\n***********************\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "//", "%", "divmod()", "pow()",\n "**", "<<", ">>", "&", "^", "|"). For instance, to evaluate the\n expression "x + y", where *x* is an instance of a class that has an\n "__add__()" method, "x.__add__(y)" is called. The "__divmod__()"\n method should be the equivalent to using "__floordiv__()" and\n "__mod__()"; it should not be related to "__truediv__()". Note\n that "__pow__()" should be defined to accept an optional third\n argument if the ternary version of the built-in "pow()" function is\n to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "//", "%", "divmod()", "pow()",\n "**", "<<", ">>", "&", "^", "|") with reflected (swapped) operands.\n These functions are only called if the left operand does not\n support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "/=", "//=", "%=", "**=", "<<=",\n ">>=", "&=", "^=", "|="). These methods should attempt to do the\n operation in-place (modifying *self*) and return the result (which\n could be, but does not have to be, *self*). If a specific method\n is not defined, the augmented assignment falls back to the normal\n methods. For instance, to execute the statement "x += y", where\n *x* is an instance of a class that has an "__iadd__()" method,\n "x.__iadd__(y)" is called. If *x* is an instance of a class that\n does not define a "__iadd__()" method, "x.__add__(y)" and\n "y.__radd__(x)" are considered, as with the evaluation of "x + y".\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()". Also called whenever\n Python needs an integer object (such as in slicing, or in the\n built-in "bin()", "hex()" and "oct()" functions). Must return an\n integer.\n', + 'objects': '\nObjects, values and types\n*************************\n\n*Objects* are Python\'s abstraction for data. All data in a Python\nprogram is represented by objects or by relations between objects. (In\na sense, and in conformance to Von Neumann\'s model of a "stored\nprogram computer," code is also represented by objects.)\n\nEvery object has an identity, a type and a value. An object\'s\n*identity* never changes once it has been created; you may think of it\nas the object\'s address in memory. The \'"is"\' operator compares the\nidentity of two objects; the "id()" function returns an integer\nrepresenting its identity.\n\n**CPython implementation detail:** For CPython, "id(x)" is the memory\naddress where "x" is stored.\n\nAn object\'s type determines the operations that the object supports\n(e.g., "does it have a length?") and also defines the possible values\nfor objects of that type. The "type()" function returns an object\'s\ntype (which is an object itself). Like its identity, an object\'s\n*type* is also unchangeable. [1]\n\nThe *value* of some objects can change. Objects whose value can\nchange are said to be *mutable*; objects whose value is unchangeable\nonce they are created are called *immutable*. (The value of an\nimmutable container object that contains a reference to a mutable\nobject can change when the latter\'s value is changed; however the\ncontainer is still considered immutable, because the collection of\nobjects it contains cannot be changed. So, immutability is not\nstrictly the same as having an unchangeable value, it is more subtle.)\nAn object\'s mutability is determined by its type; for instance,\nnumbers, strings and tuples are immutable, while dictionaries and\nlists are mutable.\n\nObjects are never explicitly destroyed; however, when they become\nunreachable they may be garbage-collected. An implementation is\nallowed to postpone garbage collection or omit it altogether --- it is\na matter of implementation quality how garbage collection is\nimplemented, as long as no objects are collected that are still\nreachable.\n\n**CPython implementation detail:** CPython currently uses a reference-\ncounting scheme with (optional) delayed detection of cyclically linked\ngarbage, which collects most objects as soon as they become\nunreachable, but is not guaranteed to collect garbage containing\ncircular references. See the documentation of the "gc" module for\ninformation on controlling the collection of cyclic garbage. Other\nimplementations act differently and CPython may change. Do not depend\non immediate finalization of objects when they become unreachable (ex:\nalways close files).\n\nNote that the use of the implementation\'s tracing or debugging\nfacilities may keep objects alive that would normally be collectable.\nAlso note that catching an exception with a \'"try"..."except"\'\nstatement may keep objects alive.\n\nSome objects contain references to "external" resources such as open\nfiles or windows. It is understood that these resources are freed\nwhen the object is garbage-collected, but since garbage collection is\nnot guaranteed to happen, such objects also provide an explicit way to\nrelease the external resource, usually a "close()" method. Programs\nare strongly recommended to explicitly close such objects. The\n\'"try"..."finally"\' statement and the \'"with"\' statement provide\nconvenient ways to do this.\n\nSome objects contain references to other objects; these are called\n*containers*. Examples of containers are tuples, lists and\ndictionaries. The references are part of a container\'s value. In\nmost cases, when we talk about the value of a container, we imply the\nvalues, not the identities of the contained objects; however, when we\ntalk about the mutability of a container, only the identities of the\nimmediately contained objects are implied. So, if an immutable\ncontainer (like a tuple) contains a reference to a mutable object, its\nvalue changes if that mutable object is changed.\n\nTypes affect almost all aspects of object behavior. Even the\nimportance of object identity is affected in some sense: for immutable\ntypes, operations that compute new values may actually return a\nreference to any existing object with the same type and value, while\nfor mutable objects this is not allowed. E.g., after "a = 1; b = 1",\n"a" and "b" may or may not refer to the same object with the value\none, depending on the implementation, but after "c = []; d = []", "c"\nand "d" are guaranteed to refer to two different, unique, newly\ncreated empty lists. (Note that "c = d = []" assigns the same object\nto both "c" and "d".)\n', + 'operator-summary': '\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedences in Python,\nfrom lowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for comparisons, including\ntests, which all have the same precedence and chain from left to right\n--- see section *Comparisons* --- and exponentiation, which groups\nfrom right to left).\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| "lambda" | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| "if" -- "else" | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| "or" | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| "and" | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| "not" "x" | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| "in", "not in", "is", "is not", "<", "<=", ">", | Comparisons, including membership |\n| ">=", "!=", "==" | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| "|" | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| "^" | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| "&" | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| "<<", ">>" | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| "+", "-" | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| "*", "/", "//", "%" | Multiplication, division, remainder |\n+-------------------------------------------------+---------------------------------------+\n| "+x", "-x", "~x" | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| "**" | Exponentiation [6] |\n+-------------------------------------------------+---------------------------------------+\n| "x[index]", "x[index:index]", | Subscription, slicing, call, |\n| "x(arguments...)", "x.attribute" | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| "(expressions...)", "[expressions...]", "{key: | Binding or tuple display, list |\n| value...}", "{expressions...}" | display, dictionary display, set |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] While "abs(x%y) < abs(y)" is true mathematically, for floats\n it may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that "-1e-100 % 1e100" have the same\n sign as "1e100", the computed result is "-1e-100 + 1e100", which\n is numerically exactly equal to "1e100". The function\n "math.fmod()" returns a result whose sign matches the sign of the\n first argument instead, and so returns "-1e-100" in this case.\n Which approach is more appropriate depends on the application.\n\n[2] If x is very close to an exact integer multiple of y, it\'s\n possible for "x//y" to be one larger than "(x-x%y)//y" due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that "divmod(x,y)[0] * y + x % y" be very close\n to "x".\n\n[3] While comparisons between strings make sense at the byte\n level, they may be counter-intuitive to users. For example, the\n strings ""\\u00C7"" and ""\\u0327\\u0043"" compare differently, even\n though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using "unicodedata.normalize()".\n\n[4] Due to automatic garbage-collection, free lists, and the\n dynamic nature of descriptors, you may notice seemingly unusual\n behaviour in certain uses of the "is" operator, like those\n involving comparisons between instance methods, or constants.\n Check their documentation for more info.\n\n[5] The "%" operator is also used for string formatting; the same\n precedence applies.\n\n[6] The power operator "**" binds less tightly than an arithmetic\n or bitwise unary operator on its right, that is, "2**-1" is "0.5".\n', + 'pass': '\nThe "pass" statement\n********************\n\n pass_stmt ::= "pass"\n\n"pass" is a null operation --- when it is executed, nothing happens.\nIt is useful as a placeholder when a statement is required\nsyntactically, but no code needs to be executed, for example:\n\n def f(arg): pass # a function that does nothing (yet)\n\n class C: pass # a class with no methods (yet)\n', + 'power': '\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= primary ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): "-1**2" results in "-1".\n\nThe power operator has the same semantics as the built-in "pow()"\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type, and the result is of that type.\n\nFor int operands, the result has the same type as the operands unless\nthe second argument is negative; in that case, all arguments are\nconverted to float and a float result is delivered. For example,\n"10**2" returns "100", but "10**-2" returns "0.01".\n\nRaising "0.0" to a negative power results in a "ZeroDivisionError".\nRaising a negative number to a fractional power results in a "complex"\nnumber. (In earlier versions it raised a "ValueError".)\n', + 'raise': '\nThe "raise" statement\n*********************\n\n raise_stmt ::= "raise" [expression ["from" expression]]\n\nIf no expressions are present, "raise" re-raises the last exception\nthat was active in the current scope. If no exception is active in\nthe current scope, a "RuntimeError" exception is raised indicating\nthat this is an error.\n\nOtherwise, "raise" evaluates the first expression as the exception\nobject. It must be either a subclass or an instance of\n"BaseException". If it is a class, the exception instance will be\nobtained when needed by instantiating the class with no arguments.\n\nThe *type* of the exception is the exception instance\'s class, the\n*value* is the instance itself.\n\nA traceback object is normally created automatically when an exception\nis raised and attached to it as the "__traceback__" attribute, which\nis writable. You can create an exception and set your own traceback in\none step using the "with_traceback()" exception method (which returns\nthe same exception instance, with its traceback set to its argument),\nlike so:\n\n raise Exception("foo occurred").with_traceback(tracebackobj)\n\nThe "from" clause is used for exception chaining: if given, the second\n*expression* must be another exception class or instance, which will\nthen be attached to the raised exception as the "__cause__" attribute\n(which is writable). If the raised exception is not handled, both\nexceptions will be printed:\n\n >>> try:\n ... print(1 / 0)\n ... except Exception as exc:\n ... raise RuntimeError("Something bad happened") from exc\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n The above exception was the direct cause of the following exception:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nA similar mechanism works implicitly if an exception is raised inside\nan exception handler: the previous exception is then attached as the\nnew exception\'s "__context__" attribute:\n\n >>> try:\n ... print(1 / 0)\n ... except:\n ... raise RuntimeError("Something bad happened")\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n During handling of the above exception, another exception occurred:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information about handling exceptions is in section\n*The try statement*.\n', + 'return': '\nThe "return" statement\n**********************\n\n return_stmt ::= "return" [expression_list]\n\n"return" may only occur syntactically nested in a function definition,\nnot within a nested class definition.\n\nIf an expression list is present, it is evaluated, else "None" is\nsubstituted.\n\n"return" leaves the current function call with the expression list (or\n"None") as return value.\n\nWhen "return" passes control out of a "try" statement with a "finally"\nclause, that "finally" clause is executed before really leaving the\nfunction.\n\nIn a generator function, the "return" statement indicates that the\ngenerator is done and will cause "StopIteration" to be raised. The\nreturned value (if any) is used as an argument to construct\n"StopIteration" and becomes the "StopIteration.value" attribute.\n', + 'sequence-types': '\nEmulating container types\n*************************\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method "keys()".\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n', + 'shifting': '\nShifting operations\n*******************\n\nThe shifting operations have lower priority than the arithmetic\noperations:\n\n shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr\n\nThese operators accept integers as arguments. They shift the first\nargument to the left or right by the number of bits given by the\nsecond argument.\n\nA right shift by *n* bits is defined as floor division by "pow(2,n)".\nA left shift by *n* bits is defined as multiplication with "pow(2,n)".\n\nNote: In the current implementation, the right-hand operand is\n required to be at most "sys.maxsize". If the right-hand operand is\n larger than "sys.maxsize" an "OverflowError" exception is raised.\n', + 'slicings': '\nSlicings\n********\n\nA slicing selects a range of items in a sequence object (e.g., a\nstring, tuple or list). Slicings may be used as expressions or as\ntargets in assignment or "del" statements. The syntax for a slicing:\n\n slicing ::= primary "[" slice_list "]"\n slice_list ::= slice_item ("," slice_item)* [","]\n slice_item ::= expression | proper_slice\n proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]\n lower_bound ::= expression\n upper_bound ::= expression\n stride ::= expression\n\nThere is ambiguity in the formal syntax here: anything that looks like\nan expression list also looks like a slice list, so any subscription\ncan be interpreted as a slicing. Rather than further complicating the\nsyntax, this is disambiguated by defining that in this case the\ninterpretation as a subscription takes priority over the\ninterpretation as a slicing (this is the case if the slice list\ncontains no proper slice).\n\nThe semantics for a slicing are as follows. The primary must evaluate\nto a mapping object, and it is indexed (using the same "__getitem__()"\nmethod as normal subscription) with a key that is constructed from the\nslice list, as follows. If the slice list contains at least one\ncomma, the key is a tuple containing the conversion of the slice\nitems; otherwise, the conversion of the lone slice item is the key.\nThe conversion of a slice item that is an expression is that\nexpression. The conversion of a proper slice is a slice object (see\nsection *The standard type hierarchy*) whose "start", "stop" and\n"step" attributes are the values of the expressions given as lower\nbound, upper bound and stride, respectively, substituting "None" for\nmissing expressions.\n', + 'specialattrs': '\nSpecial Attributes\n******************\n\nThe implementation adds a few special read-only attributes to several\nobject types, where they are relevant. Some of these are not reported\nby the "dir()" built-in function.\n\nobject.__dict__\n\n A dictionary or other mapping object used to store an object\'s\n (writable) attributes.\n\ninstance.__class__\n\n The class to which a class instance belongs.\n\nclass.__bases__\n\n The tuple of base classes of a class object.\n\nclass.__name__\n\n The name of the class or type.\n\nclass.__qualname__\n\n The *qualified name* of the class or type.\n\n New in version 3.3.\n\nclass.__mro__\n\n This attribute is a tuple of classes that are considered when\n looking for base classes during method resolution.\n\nclass.mro()\n\n This method can be overridden by a metaclass to customize the\n method resolution order for its instances. It is called at class\n instantiation, and its result is stored in "__mro__".\n\nclass.__subclasses__()\n\n Each class keeps a list of weak references to its immediate\n subclasses. This method returns a list of all those references\n still alive. Example:\n\n >>> int.__subclasses__()\n []\n\n-[ Footnotes ]-\n\n[1] Additional information on these special methods may be found\n in the Python Reference Manual (*Basic customization*).\n\n[2] As a consequence, the list "[1, 2]" is considered equal to\n "[1.0, 2.0]", and similarly for tuples.\n\n[3] They must have since the parser can\'t tell the type of the\n operands.\n\n[4] Cased characters are those with general category property\n being one of "Lu" (Letter, uppercase), "Ll" (Letter, lowercase),\n or "Lt" (Letter, titlecase).\n\n[5] To format only a tuple you should therefore provide a\n singleton tuple whose only element is the tuple to be formatted.\n', + 'specialnames': '\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "type(x).__getitem__(x, i)".\nExcept where mentioned, attempts to execute an operation raise an\nexception when no appropriate method is defined (typically\n"AttributeError" or "TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called when the instance is created. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])". As a special constraint on\n constructors, no value may be returned; doing so will cause a\n "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing "None" in\n "sys.last_traceback". Circular references which are garbage are\n detected when the option cycle detector is enabled (it\'s on by\n default), but can only be cleaned up if there are no Python-\n level "__del__()" methods involved. Refer to the documentation\n for the "gc" module for more information about how "__del__()"\n methods are handled by the cycle detector, particularly the\n description of the "garbage" value.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)""\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable").\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n .__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n class, *__slots__* reserves space for the declared variables and\n prevents the automatic creation of *__dict__* and *__weakref__* for\n each instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using "type()". The class body is\nexecuted in a new namespace and the class name is bound locally to the\nresult of "type(name, bases, namespace)".\n\nThe class creation process can be customised by passing the\n"metaclass" keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both "MyClass" and "MySubclass" are instances\nof "Meta":\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then "type()" is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n "type()", then it is used directly as the metaclass\n\n* if an instance of "type()" is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. "type(cls)") of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with "TypeError".\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a "__prepare__" attribute,\nit is called as "namespace = metaclass.__prepare__(name, bases,\n**kwds)" (where the additional keyword arguments, if any, come from\nthe class definition).\n\nIf the metaclass has no "__prepare__" attribute, then the class\nnamespace is initialised as an empty "dict()" instance.\n\nSee also: **PEP 3115** - Metaclasses in Python 3000\n\n Introduced the "__prepare__" namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as "exec(body, globals(),\nnamespace)". The key difference from a normal call to "exec()" is that\nlexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling "metaclass(name, bases,\nnamespace, **kwds)" (the additional keywords passed here are the same\nas those passed to "__prepare__").\n\nThis class object is the one that will be referenced by the zero-\nargument form of "super()". "__class__" is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either "__class__" or "super". This allows the zero argument form\nof "super()" to correctly identify the class being defined based on\nlexical scoping, while the class or instance that was used to make the\ncurrent call is identified based on the first argument passed to the\nmethod.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also: **PEP 3135** - New super\n\n Describes the implicit "__class__" closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n"collections.OrderedDict" to remember the order that class members\nwere defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s "__prepare__()" method which returns an\nempty "collections.OrderedDict". That mapping records the methods and\nattributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s "__new__()" method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called "members".\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method "keys()".\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "//", "%", "divmod()", "pow()",\n "**", "<<", ">>", "&", "^", "|"). For instance, to evaluate the\n expression "x + y", where *x* is an instance of a class that has an\n "__add__()" method, "x.__add__(y)" is called. The "__divmod__()"\n method should be the equivalent to using "__floordiv__()" and\n "__mod__()"; it should not be related to "__truediv__()". Note\n that "__pow__()" should be defined to accept an optional third\n argument if the ternary version of the built-in "pow()" function is\n to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "//", "%", "divmod()", "pow()",\n "**", "<<", ">>", "&", "^", "|") with reflected (swapped) operands.\n These functions are only called if the left operand does not\n support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "/=", "//=", "%=", "**=", "<<=",\n ">>=", "&=", "^=", "|="). These methods should attempt to do the\n operation in-place (modifying *self*) and return the result (which\n could be, but does not have to be, *self*). If a specific method\n is not defined, the augmented assignment falls back to the normal\n methods. For instance, to execute the statement "x += y", where\n *x* is an instance of a class that has an "__iadd__()" method,\n "x.__iadd__(y)" is called. If *x* is an instance of a class that\n does not define a "__iadd__()" method, "x.__add__(y)" and\n "y.__radd__(x)" are considered, as with the evaluation of "x + y".\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()". Also called whenever\n Python needs an integer object (such as in slicing, or in the\n built-in "bin()", "hex()" and "oct()" functions). Must return an\n integer.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n\n-[ Footnotes ]-\n\n[1] It *is* possible in some cases to change an object\'s type,\n under certain controlled conditions. It generally isn\'t a good\n idea though, since it can lead to some very strange behaviour if\n it is handled incorrectly.\n\n[2] For operands of the same type, it is assumed that if the non-\n reflected method (such as "__add__()") fails the operation is not\n supported, which is why the reflected method is not called.\n', + 'string-methods': '\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see "str.format()",\n*Format String Syntax* and *String Formatting*) and the other based on\nC "printf" style formatting that handles a narrower range of types and\nis slightly harder to use correctly, but is often faster for the cases\nit can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the "re" module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter "\'\xc3\x9f\'" is equivalent to ""ss"".\n Since it is already lowercase, "lower()" would do nothing to "\'\xc3\x9f\'";\n "casefold()" converts it to ""ss"".\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is a space).\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is "\'utf-8\'". *errors* may be given to set a different\n error handling scheme. The default for *errors* is "\'strict\'",\n meaning that encoding errors raise a "UnicodeError". Other possible\n values are "\'ignore\'", "\'replace\'", "\'xmlcharrefreplace\'",\n "\'backslashreplace\'" and any other name registered via\n "codecs.register_error()", see section *Codec Base Classes*. For a\n list of possible encodings, see section *Standard Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to "str.format(**mapping)", except that "mapping" is used\n directly and not copied to a "dict". This is useful if for example\n "mapping" is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character "c"\n is alphanumeric if one of the following returns "True":\n "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()".\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use "keyword.iskeyword()" to test for reserved identifiers such as\n "def" and "class".\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when "repr()" is\n invoked on a string. It has no bearing on the handling of strings\n written to "sys.stdout" or "sys.stderr".)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A "TypeError" will be raised if there are\n any non-string values in *iterable*, including "bytes" objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n "str.translate()".\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example, "\' 1 2 3 \'.split()" returns "[\'1\', \'2\', \'3\']", and\n "\' 1 2 3 \'.split(None, 1)" returns "[\'1\', \'2 3 \']".\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example, "\'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()" returns "[\'ab\n c\', \'\', \'de fg\', \'kl\']", while the same call with\n "splitlines(True)" returns "[\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']".\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line.\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n "s.swapcase().swapcase() == s".\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(map)\n\n Return a copy of the *s* where all characters have been mapped\n through the *map* which must be a dictionary of Unicode ordinals\n (integers) to Unicode ordinals, strings or "None". Unmapped\n characters are left untouched. Characters mapped to "None" are\n deleted.\n\n You can use "str.maketrans()" to create a translation map from\n character-to-character mappings in different formats.\n\n Note: An even more flexible approach is to create a custom\n character mapping codec using the "codecs" module (see\n "encodings.cp1251" for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to "len(s)".\n', + 'strings': '\nString and Bytes literals\n*************************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "R" | "U"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'" | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | stringescapeseq\n longstringitem ::= longstringchar | stringescapeseq\n shortstringchar ::= \n longstringchar ::= \n stringescapeseq ::= "\\" \n\n bytesliteral ::= bytesprefix(shortbytes | longbytes)\n bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"\n shortbytes ::= "\'" shortbytesitem* "\'" | \'"\' shortbytesitem* \'"\'\n longbytes ::= "\'\'\'" longbytesitem* "\'\'\'" | \'"""\' longbytesitem* \'"""\'\n shortbytesitem ::= shortbyteschar | bytesescapeseq\n longbytesitem ::= longbyteschar | bytesescapeseq\n shortbyteschar ::= \n longbyteschar ::= \n bytesescapeseq ::= "\\" \n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the "stringprefix" or "bytesprefix"\nand the rest of the literal. The source character set is defined by\nthe encoding declaration; it is UTF-8 if no encoding declaration is\ngiven in the source file; see section *Encoding declarations*.\n\nIn plain English: Both types of literals can be enclosed in matching\nsingle quotes ("\'") or double quotes ("""). They can also be enclosed\nin matching groups of three single or double quotes (these are\ngenerally referred to as *triple-quoted strings*). The backslash\n("\\") character is used to escape characters that otherwise have a\nspecial meaning, such as newline, backslash itself, or the quote\ncharacter.\n\nBytes literals are always prefixed with "\'b\'" or "\'B\'"; they produce\nan instance of the "bytes" type instead of the "str" type. They may\nonly contain ASCII characters; bytes with a numeric value of 128 or\ngreater must be expressed with escapes.\n\nAs of Python 3.3 it is possible again to prefix unicode strings with a\n"u" prefix to simplify maintenance of dual 2.x and 3.x codebases.\n\nBoth string and bytes literals may optionally be prefixed with a\nletter "\'r\'" or "\'R\'"; such strings are called *raw strings* and treat\nbackslashes as literal characters. As a result, in string literals,\n"\'\\U\'" and "\'\\u\'" escapes in raw strings are not treated specially.\nGiven that Python 2.x\'s raw unicode literals behave differently than\nPython 3.x\'s the "\'ur\'" syntax is not supported.\n\n New in version 3.3: The "\'rb\'" prefix of raw bytes literals has\n been added as a synonym of "\'br\'".\n\n New in version 3.3: Support for the unicode legacy literal\n ("u\'value\'") was reintroduced to simplify the maintenance of dual\n Python 2.x and 3.x codebases. See **PEP 414** for more information.\n\nIn triple-quoted strings, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the string. (A "quote" is the character used to open the\nstring, i.e. either "\'" or """.)\n\nUnless an "\'r\'" or "\'R\'" prefix is present, escape sequences in\nstrings are interpreted according to rules similar to those used by\nStandard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n| "\\ooo" | Character with octal value *ooo* | (1,3) |\n+-------------------+-----------------------------------+---------+\n| "\\xhh" | Character with hex value *hh* | (2,3) |\n+-------------------+-----------------------------------+---------+\n\nEscape sequences only recognized in string literals are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\N{name}" | Character named *name* in the | (4) |\n+-------------------+-----------------------------------+---------+\n| "\\uxxxx" | Character with 16-bit hex value | (5) |\n+-------------------+-----------------------------------+---------+\n| "\\Uxxxxxxxx" | Character with 32-bit hex value | (6) |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. As in Standard C, up to three octal digits are accepted.\n\n2. Unlike in Standard C, exactly two hex digits are required.\n\n3. In a bytes literal, hexadecimal and octal escapes denote the\n byte with the given value. In a string literal, these escapes\n denote a Unicode character with the given value.\n\n4. Changed in version 3.3: Support for name aliases [1] has been\n added.\n\n5. Individual code units which form parts of a surrogate pair can\n be encoded using this escape sequence. Exactly four hex digits are\n required.\n\n6. Any Unicode character can be encoded this way. Exactly eight\n hex digits are required.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the string*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences only recognized in string\nliterals fall into the category of unrecognized escapes for bytes\nliterals.\n\nEven in a raw string, string quotes can be escaped with a backslash,\nbut the backslash remains in the string; for example, "r"\\""" is a\nvalid string literal consisting of two characters: a backslash and a\ndouble quote; "r"\\"" is not a valid string literal (even a raw string\ncannot end in an odd number of backslashes). Specifically, *a raw\nstring cannot end in a single backslash* (since the backslash would\nescape the following quote character). Note also that a single\nbackslash followed by a newline is interpreted as those two characters\nas part of the string, *not* as a line continuation.\n', + 'subscriptions': '\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object that supports subscription,\ne.g. a list or dictionary. User-defined objects can support\nsubscription by defining a "__getitem__()" method.\n\nFor built-in objects, there are two types of objects that support\nsubscription:\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to\nan integer or a slice (as discussed in the following section).\n\nThe formal syntax makes no special provision for negative indices in\nsequences; however, built-in sequences all provide a "__getitem__()"\nmethod that interprets negative indices by adding the length of the\nsequence to the index (so that "x[-1]" selects the last item of "x").\nThe resulting value must be a nonnegative integer less than the number\nof items in the sequence, and the subscription selects the item whose\nindex is that value (counting from zero). Since the support for\nnegative indices and slicing occurs in the object\'s "__getitem__()"\nmethod, subclasses overriding this method will need to explicitly add\nthat support.\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n', + 'truth': '\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an "if" or\n"while" condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* "None"\n\n* "False"\n\n* zero of any numeric type, for example, "0", "0.0", "0j".\n\n* any empty sequence, for example, "\'\'", "()", "[]".\n\n* any empty mapping, for example, "{}".\n\n* instances of user-defined classes, if the class defines a\n "__bool__()" or "__len__()" method, when that method returns the\n integer zero or "bool" value "False". [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn "0" or "False" for false and "1" or "True" for true, unless\notherwise stated. (Important exception: the Boolean operations "or"\nand "and" always return one of their operands.)\n', + 'try': '\nThe "try" statement\n*******************\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" target]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be access via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n def f():\n try:\n 1/0\n finally:\n return 42\n\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n', + 'types': '\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.), although such additions\nwill often be provided via the standard library instead.\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name "None". It\n is used to signify the absence of a value in many situations, e.g.,\n it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n "NotImplemented". Numeric methods and rich comparison methods may\n return this value if they do not implement the operation for the\n operands provided. (The interpreter will then try the reflected\n operation, or some other fallback, depending on the operator.) Its\n truth value is true.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the literal "..." or the\n built-in name "Ellipsis". Its truth value is true.\n\n"numbers.Number"\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n "numbers.Integral"\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are two types of integers:\n\n Integers ("int")\n\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans ("bool")\n These represent the truth values False and True. The two\n objects representing the values "False" and "True" are the\n only Boolean objects. The Boolean type is a subtype of the\n integer type, and Boolean values behave like the values 0 and\n 1, respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ""False"" or\n ""True"" are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers.\n\n "numbers.Real" ("float")\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these is\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n "numbers.Complex" ("complex")\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number "z" can be retrieved through the read-only\n attributes "z.real" and "z.imag".\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function "len()" returns the number of items\n of a sequence. When the length of a sequence is *n*, the index set\n contains the numbers 0, 1, ..., *n*-1. Item *i* of sequence *a* is\n selected by "a[i]".\n\n Sequences also support slicing: "a[i:j]" selects all items with\n index *k* such that *i* "<=" *k* "<" *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: "a[i:j:k]" selects all items of *a* with index *x* where\n "x = i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n A string is a sequence of values that represent Unicode\n codepoints. All the codepoints in range "U+0000 - U+10FFFF"\n can be represented in a string. Python doesn\'t have a "chr"\n type, and every character in the string is represented as a\n string object with length "1". The built-in function "ord()"\n converts a character to its codepoint (as an integer);\n "chr()" converts an integer in range "0 - 10FFFF" to the\n corresponding character. "str.encode()" can be used to\n convert a "str" to "bytes" using the given encoding, and\n "bytes.decode()" can be used to achieve the opposite.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Bytes\n A bytes object is an immutable array. The items are 8-bit\n bytes, represented by integers in the range 0 <= x < 256.\n Bytes literals (like "b\'abc\'") and the built-in function\n "bytes()" can be used to construct bytes objects. Also,\n bytes objects can be decoded to strings via the "decode()"\n method.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and "del" (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in "bytearray()" constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module "array" provides an additional example of a\n mutable sequence type, as does the "collections" module.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function "len()"\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., "1" and\n "1.0"), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n "set()" constructor and can be modified afterwards by several\n methods, such as "add()".\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in "frozenset()" constructor. As a frozenset is immutable\n and *hashable*, it can be used again as an element of another\n set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation "a[k]" selects the item indexed by "k"\n from the mapping "a"; this can be used in expressions and as the\n target of assignments or "del" statements. The built-in function\n "len()" returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., "1" and "1.0")\n then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the "{...}"\n notation (see section *Dictionary displays*).\n\n The extension modules "dbm.ndbm" and "dbm.gnu" provide\n additional examples of mapping types, as does the "collections"\n module.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +---------------------------+---------------------------------+-------------+\n +===========================+=================================+=============+\n | "__doc__" | The function\'s documentation | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__name__" | The function\'s name | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__qualname__" | The function\'s *qualified name* | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__module__" | The name of the module the | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__defaults__" | A tuple containing default | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__code__" | The code object representing | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__globals__" | A reference to the dictionary | Read-only |\n +---------------------------+---------------------------------+-------------+\n | "__dict__" | The namespace supporting | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__closure__" | "None" or a tuple of cells that | Read-only |\n +---------------------------+---------------------------------+-------------+\n | "__annotations__" | A dict containing annotations | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__kwdefaults__" | A dict containing defaults for | Writable |\n +---------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n Instance methods\n An instance method object combines a class, a class instance and\n any callable object (normally a user-defined function).\n\n Special read-only attributes: "__self__" is the class instance\n object, "__func__" is the function object; "__doc__" is the\n method\'s documentation (same as "__func__.__doc__"); "__name__"\n is the method name (same as "__func__.__name__"); "__module__"\n is the name of the module the method was defined in, or "None"\n if unavailable.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object or a class\n method object.\n\n When an instance method object is created by retrieving a user-\n defined function object from a class via one of its instances,\n its "__self__" attribute is the instance, and the method object\n is said to be bound. The new method\'s "__func__" attribute is\n the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the "__func__"\n attribute of the new instance is not the original method object\n but its "__func__" attribute.\n\n When an instance method object is created by retrieving a class\n method object from a class or instance, its "__self__" attribute\n is the class itself, and its "__func__" attribute is the\n function object underlying the class method.\n\n When an instance method object is called, the underlying\n function ("__func__") is called, inserting the class instance\n ("__self__") in front of the argument list. For instance, when\n "C" is a class which contains a definition for a function "f()",\n and "x" is an instance of "C", calling "x.f(1)" is equivalent to\n calling "C.f(x, 1)".\n\n When an instance method object is derived from a class method\n object, the "class instance" stored in "__self__" will actually\n be the class itself, so that calling either "x.f(1)" or "C.f(1)"\n is equivalent to calling "f(C,1)" where "f" is the underlying\n function.\n\n Note that the transformation from function object to instance\n method object happens each time the attribute is retrieved from\n the instance. In some cases, a fruitful optimization is to\n assign the attribute to a local variable and call that local\n variable. Also notice that this transformation only happens for\n user-defined functions; other callable objects (and all non-\n callable objects) are retrieved without transformation. It is\n also important to note that user-defined functions which are\n attributes of a class instance are not converted to bound\n methods; this *only* happens when the function is an attribute\n of the class.\n\n Generator functions\n A function or method which uses the "yield" statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s "iterator.__next__()" method will cause the\n function to execute until it provides a value using the "yield"\n statement. When the function executes a "return" statement or\n falls off the end, a "StopIteration" exception is raised and the\n iterator will have reached the end of the set of values to be\n returned.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are "len()" and "math.sin()"\n ("math" is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: "__doc__" is the function\'s documentation\n string, or "None" if unavailable; "__name__" is the function\'s\n name; "__self__" is set to "None" (but see the next item);\n "__module__" is the name of the module the function was defined\n in or "None" if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n "alist.append()", assuming *alist* is a list object. In this\n case, the special read-only attribute "__self__" is set to the\n object denoted by *alist*.\n\n Classes\n Classes are callable. These objects normally act as factories\n for new instances of themselves, but variations are possible for\n class types that override "__new__()". The arguments of the\n call are passed to "__new__()" and, in the typical case, to\n "__init__()" to initialize the new instance.\n\n Class Instances\n Instances of arbitrary classes can be made callable by defining\n a "__call__()" method in their class.\n\nModules\n Modules are a basic organizational unit of Python code, and are\n created by the *import system* as invoked either by the "import"\n statement (see "import"), or by calling functions such as\n "importlib.import_module()" and built-in "__import__()". A module\n object has a namespace implemented by a dictionary object (this is\n the dictionary referenced by the "__globals__" attribute of\n functions defined in the module). Attribute references are\n translated to lookups in this dictionary, e.g., "m.x" is equivalent\n to "m.__dict__["x"]". A module object does not contain the code\n object used to initialize the module (since it isn\'t needed once\n the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n\n Special read-only attribute: "__dict__" is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: "__name__" is the module\'s name;\n "__doc__" is the module\'s documentation string, or "None" if\n unavailable; "__file__" is the pathname of the file from which the\n module was loaded, if it was loaded from a file. The "__file__"\n attribute may be missing for certain types of modules, such as C\n modules that are statically linked into the interpreter; for\n extension modules loaded dynamically from a shared library, it is\n the pathname of the shared library file.\n\nCustom classes\n Custom class types are typically created by class definitions (see\n section *Class definitions*). A class has a namespace implemented\n by a dictionary object. Class attribute references are translated\n to lookups in this dictionary, e.g., "C.x" is translated to\n "C.__dict__["x"]" (although there are a number of hooks which allow\n for other means of locating attributes). When the attribute name is\n not found there, the attribute search continues in the base\n classes. This search of the base classes uses the C3 method\n resolution order which behaves correctly even in the presence of\n \'diamond\' inheritance structures where there are multiple\n inheritance paths leading back to a common ancestor. Additional\n details on the C3 MRO used by Python can be found in the\n documentation accompanying the 2.3 release at\n http://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class "C", say) would yield a\n class method object, it is transformed into an instance method\n object whose "__self__" attributes is "C". When it would yield a\n static method object, it is transformed into the object wrapped by\n the static method object. See section *Implementing Descriptors*\n for another way in which attributes retrieved from a class may\n differ from those actually contained in its "__dict__".\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: "__name__" is the class name; "__module__" is\n the module name in which the class was defined; "__dict__" is the\n dictionary containing the class\'s namespace; "__bases__" is a tuple\n (possibly empty or a singleton) containing the base classes, in the\n order of their occurrence in the base class list; "__doc__" is the\n class\'s documentation string, or None if undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object, it is transformed into an instance method object\n whose "__self__" attribute is the instance. Static method and\n class method objects are also transformed; see above under\n "Classes". See section *Implementing Descriptors* for another way\n in which attributes of a class retrieved via its instances may\n differ from the objects actually stored in the class\'s "__dict__".\n If no class attribute is found, and the object\'s class has a\n "__getattr__()" method, that is called to satisfy the lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n "__setattr__()" or "__delattr__()" method, this is called instead\n of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: "__dict__" is the attribute dictionary;\n "__class__" is the instance\'s class.\n\nI/O objects (also known as file objects)\n A *file object* represents an open file. Various shortcuts are\n available to create file objects: the "open()" built-in function,\n and also "os.popen()", "os.fdopen()", and the "makefile()" method\n of socket objects (and perhaps by other functions or methods\n provided by extension modules).\n\n The objects "sys.stdin", "sys.stdout" and "sys.stderr" are\n initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams; they are all open in text\n mode and therefore follow the interface defined by the\n "io.TextIOBase" abstract class.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: "co_name" gives the function name;\n "co_argcount" is the number of positional arguments (including\n arguments with default values); "co_nlocals" is the number of\n local variables used by the function (including arguments);\n "co_varnames" is a tuple containing the names of the local\n variables (starting with the argument names); "co_cellvars" is a\n tuple containing the names of local variables that are\n referenced by nested functions; "co_freevars" is a tuple\n containing the names of free variables; "co_code" is a string\n representing the sequence of bytecode instructions; "co_consts"\n is a tuple containing the literals used by the bytecode;\n "co_names" is a tuple containing the names used by the bytecode;\n "co_filename" is the filename from which the code was compiled;\n "co_firstlineno" is the first line number of the function;\n "co_lnotab" is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); "co_stacksize" is the required stack size\n (including local variables); "co_flags" is an integer encoding a\n number of flags for the interpreter.\n\n The following flag bits are defined for "co_flags": bit "0x04"\n is set if the function uses the "*arguments" syntax to accept an\n arbitrary number of positional arguments; bit "0x08" is set if\n the function uses the "**keywords" syntax to accept arbitrary\n keyword arguments; bit "0x20" is set if the function is a\n generator.\n\n Future feature declarations ("from __future__ import division")\n also use bits in "co_flags" to indicate whether a code object\n was compiled with a particular feature enabled: bit "0x2000" is\n set if the function was compiled with future division enabled;\n bits "0x10" and "0x1000" were used in earlier versions of\n Python.\n\n Other bits in "co_flags" are reserved for internal use.\n\n If a code object represents a function, the first item in\n "co_consts" is the documentation string of the function, or\n "None" if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: "f_back" is to the previous stack\n frame (towards the caller), or "None" if this is the bottom\n stack frame; "f_code" is the code object being executed in this\n frame; "f_locals" is the dictionary used to look up local\n variables; "f_globals" is used for global variables;\n "f_builtins" is used for built-in (intrinsic) names; "f_lasti"\n gives the precise instruction (this is an index into the\n bytecode string of the code object).\n\n Special writable attributes: "f_trace", if not "None", is a\n function called at the start of each source code line (this is\n used by the debugger); "f_lineno" is the current line number of\n the frame --- writing to this from within a trace function jumps\n to the given line (only for the bottom-most frame). A debugger\n can implement a Jump command (aka Set Next Statement) by writing\n to f_lineno.\n\n Traceback objects\n Traceback objects represent a stack trace of an exception. A\n traceback object is created when an exception occurs. When the\n search for an exception handler unwinds the execution stack, at\n each unwound level a traceback object is inserted in front of\n the current traceback. When an exception handler is entered,\n the stack trace is made available to the program. (See section\n *The try statement*.) It is accessible as the third item of the\n tuple returned by "sys.exc_info()". When the program contains no\n suitable handler, the stack trace is written (nicely formatted)\n to the standard error stream; if the interpreter is interactive,\n it is also made available to the user as "sys.last_traceback".\n\n Special read-only attributes: "tb_next" is the next level in the\n stack trace (towards the frame where the exception occurred), or\n "None" if there is no next level; "tb_frame" points to the\n execution frame of the current level; "tb_lineno" gives the line\n number where the exception occurred; "tb_lasti" indicates the\n precise instruction. The line number and last instruction in\n the traceback may differ from the line number of its frame\n object if the exception occurred in a "try" statement with no\n matching except clause or with a finally clause.\n\n Slice objects\n Slice objects are used to represent slices for "__getitem__()"\n methods. They are also created by the built-in "slice()"\n function.\n\n Special read-only attributes: "start" is the lower bound; "stop"\n is the upper bound; "step" is the step value; each is "None" if\n omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the slice that the slice object\n would describe if applied to a sequence of *length* items.\n It returns a tuple of three integers; respectively these are\n the *start* and *stop* indices and the *step* or stride\n length of the slice. Missing or out-of-bounds indices are\n handled in a manner consistent with regular slices.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n "staticmethod()" constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in "classmethod()" constructor.\n', + 'typesfunctions': '\nFunctions\n*********\n\nFunction objects are created by function definitions. The only\noperation on a function object is to call it: "func(argument-list)".\n\nThere are really two flavors of function objects: built-in functions\nand user-defined functions. Both support the same operation (to call\nthe function), but the implementation is different, hence the\ndifferent object types.\n\nSee *Function definitions* for more information.\n', + 'typesmapping': '\nMapping Types --- "dict"\n************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built-\nin "list", "set", and "tuple" classes, and the "collections" module.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as "1" and "1.0") then they can be used interchangeably to index\nthe same dictionary entry. (Note however, that since computers store\nfloating-point numbers as approximations it is usually unwise to use\nthem as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of "key:\nvalue" pairs within braces, for example: "{\'jack\': 4098, \'sjoerd\':\n4127}" or "{4098: \'jack\', 4127: \'sjoerd\'}", or by the "dict"\nconstructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterator*\n object. Each item in the iterable must itself be an iterator with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to "{"one": 1, "two": 2, "three": 3}":\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a "KeyError" if\n *key* is not in the map.\n\n If a subclass of dict defines a method "__missing__()", if the\n key *key* is not present, the "d[key]" operation calls that\n method with the key *key* as argument. The "d[key]" operation\n then returns or raises whatever is returned or raised by the\n "__missing__(key)" call if the key is not present. No other\n operations or methods invoke "__missing__()". If "__missing__()"\n is not defined, "KeyError" is raised. "__missing__()" must be a\n method; it cannot be an instance variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n See "collections.Counter" for a complete implementation\n including other methods helpful for accumulating and managing\n tallies.\n\n d[key] = value\n\n Set "d[key]" to *value*.\n\n del d[key]\n\n Remove "d[key]" from *d*. Raises a "KeyError" if *key* is not\n in the map.\n\n key in d\n\n Return "True" if *d* has a key *key*, else "False".\n\n key not in d\n\n Equivalent to "not key in d".\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for "iter(d.keys())".\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n classmethod fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n "fromkeys()" is a class method that returns a new dictionary.\n *value* defaults to "None".\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to "None", so\n that this method never raises a "KeyError".\n\n items()\n\n Return a new view of the dictionary\'s items ("(key, value)"\n pairs). See the *documentation of view objects*.\n\n keys()\n\n Return a new view of the dictionary\'s keys. See the\n *documentation of view objects*.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a "KeyError" is raised.\n\n popitem()\n\n Remove and return an arbitrary "(key, value)" pair from the\n dictionary.\n\n "popitem()" is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling "popitem()" raises a "KeyError".\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to "None".\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return "None".\n\n "update()" accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: "d.update(red=1,\n blue=2)".\n\n values()\n\n Return a new view of the dictionary\'s values. See the\n *documentation of view objects*.\n\nSee also: "types.MappingProxyType" can be used to create a read-only\n view of a "dict".\n\n\nDictionary view objects\n=======================\n\nThe objects returned by "dict.keys()", "dict.values()" and\n"dict.items()" are *view objects*. They provide a dynamic view on the\ndictionary\'s entries, which means that when the dictionary changes,\nthe view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of "(key, value)") in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of "(value, key)" pairs using\n "zip()": "pairs = zip(d.values(), d.keys())". Another way to\n create the same list is "pairs = [(v, k) for (k, v) in d.items()]".\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a "RuntimeError" or fail to iterate over all entries.\n\nx in dictview\n\n Return "True" if *x* is in the underlying dictionary\'s keys, values\n or items (in the latter case, *x* should be a "(key, value)"\n tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that "(key, value)" pairs are unique\nand hashable, then the items view is also set-like. (Values views are\nnot treated as set-like since the entries are generally not unique.)\nFor set-like views, all of the operations defined for the abstract\nbase class "collections.abc.Set" are available (for example, "==",\n"<", or "^").\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.keys()\n >>> values = dishes.values()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n >>> keys ^ {\'sausage\', \'juice\'}\n {\'juice\', \'sausage\', \'bacon\', \'spam\'}\n', + 'typesmethods': '\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as "append()" on lists)\nand class instance methods. Built-in methods are described with the\ntypes that support them.\n\nIf you access a method (a function defined in a class namespace)\nthrough an instance, you get a special object: a *bound method* (also\ncalled *instance method*) object. When called, it will add the "self"\nargument to the argument list. Bound methods have two special read-\nonly attributes: "m.__self__" is the object on which the method\noperates, and "m.__func__" is the function implementing the method.\nCalling "m(arg-1, arg-2, ..., arg-n)" is completely equivalent to\ncalling "m.__func__(m.__self__, arg-1, arg-2, ..., arg-n)".\n\nLike function objects, bound method objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object ("meth.__func__"), setting method\nattributes on bound methods is disallowed. Attempting to set an\nattribute on a method results in an "AttributeError" being raised. In\norder to set a method attribute, you need to explicitly set it on the\nunderlying function object:\n\n >>> class C:\n ... def method(self):\n ... pass\n ...\n >>> c = C()\n >>> c.method.whoami = \'my name is method\' # can\'t set on the method\n Traceback (most recent call last):\n File "", line 1, in \n AttributeError: \'method\' object has no attribute \'whoami\'\n >>> c.method.__func__.whoami = \'my name is method\'\n >>> c.method.whoami\n \'my name is method\'\n\nSee *The standard type hierarchy* for more information.\n', + 'typesmodules': '\nModules\n*******\n\nThe only special operation on a module is attribute access: "m.name",\nwhere *m* is a module and *name* accesses a name defined in *m*\'s\nsymbol table. Module attributes can be assigned to. (Note that the\n"import" statement is not, strictly speaking, an operation on a module\nobject; "import foo" does not require a module object named *foo* to\nexist, rather it requires an (external) *definition* for a module\nnamed *foo* somewhere.)\n\nA special attribute of every module is "__dict__". This is the\ndictionary containing the module\'s symbol table. Modifying this\ndictionary will actually change the module\'s symbol table, but direct\nassignment to the "__dict__" attribute is not possible (you can write\n"m.__dict__[\'a\'] = 1", which defines "m.a" to be "1", but you can\'t\nwrite "m.__dict__ = {}"). Modifying "__dict__" directly is not\nrecommended.\n\nModules built into the interpreter are written like this: "". If loaded from a file, they are written as\n"".\n', + 'typesseq': '\nSequence Types --- "list", "tuple", "range"\n*******************************************\n\nThere are three basic sequence types: lists, tuples, and range\nobjects. Additional sequence types tailored for processing of *binary\ndata* and *text strings* are described in dedicated sections.\n\n\nCommon Sequence Operations\n==========================\n\nThe operations in the following table are supported by most sequence\ntypes, both mutable and immutable. The "collections.abc.Sequence" ABC\nis provided to make it easier to correctly implement these operations\non custom sequence types.\n\nThis table lists the sequence operations sorted in ascending priority\n(operations in the same box have the same priority). In the table,\n*s* and *t* are sequences of the same type, *n*, *i*, *j* and *k* are\nintegers and *x* is an arbitrary object that meets any type and value\nrestrictions imposed by *s*.\n\nThe "in" and "not in" operations have the same priorities as the\ncomparison operations. The "+" (concatenation) and "*" (repetition)\noperations have the same priority as the corresponding numeric\noperations.\n\n+----------------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+============================+==================================+============+\n| "x in s" | "True" if an item of *s* is | (1) |\n+----------------------------+----------------------------------+------------+\n| "x not in s" | "False" if an item of *s* is | (1) |\n+----------------------------+----------------------------------+------------+\n| "s + t" | the concatenation of *s* and *t* | (6)(7) |\n+----------------------------+----------------------------------+------------+\n| "s * n" or "n * s" | *n* shallow copies of *s* | (2)(7) |\n+----------------------------+----------------------------------+------------+\n| "s[i]" | *i*th item of *s*, origin 0 | (3) |\n+----------------------------+----------------------------------+------------+\n| "s[i:j]" | slice of *s* from *i* to *j* | (3)(4) |\n+----------------------------+----------------------------------+------------+\n| "s[i:j:k]" | slice of *s* from *i* to *j* | (3)(5) |\n+----------------------------+----------------------------------+------------+\n+----------------------------+----------------------------------+------------+\n+----------------------------+----------------------------------+------------+\n+----------------------------+----------------------------------+------------+\n| "s.index(x[, i[, j]])" | index of the first occurrence of | (8) |\n+----------------------------+----------------------------------+------------+\n+----------------------------+----------------------------------+------------+\n\nSequences of the same type also support comparisons. In particular,\ntuples and lists are compared lexicographically by comparing\ncorresponding elements. This means that to compare equal, every\nelement must compare equal and the two sequences must be of the same\ntype and have the same length. (For full details see *Comparisons* in\nthe language reference.)\n\nNotes:\n\n1. While the "in" and "not in" operations are used only for simple\n containment testing in the general case, some specialised sequences\n (such as "str", "bytes" and "bytearray") also use them for\n subsequence testing:\n\n >>> "gg" in "eggs"\n True\n\n2. Values of *n* less than "0" are treated as "0" (which yields an\n empty sequence of the same type as *s*). Note also that the copies\n are shallow; nested structures are not copied. This often haunts\n new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that "[[]]" is a one-element list containing\n an empty list, so all three elements of "[[]] * 3" are (pointers\n to) this single empty list. Modifying any of the elements of\n "lists" modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n3. If *i* or *j* is negative, the index is relative to the end of\n the string: "len(s) + i" or "len(s) + j" is substituted. But note\n that "-0" is still "0".\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that "i <= k < j". If *i* or *j* is\n greater than "len(s)", use "len(s)". If *i* is omitted or "None",\n use "0". If *j* is omitted or "None", use "len(s)". If *i* is\n greater than or equal to *j*, the slice is empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index "x = i + n*k" such that "0 <= n <\n (j-i)/k". In other words, the indices are "i", "i+k", "i+2*k",\n "i+3*k" and so on, stopping when *j* is reached (but never\n including *j*). If *i* or *j* is greater than "len(s)", use\n "len(s)". If *i* or *j* are omitted or "None", they become "end"\n values (which end depends on the sign of *k*). Note, *k* cannot be\n zero. If *k* is "None", it is treated like "1".\n\n6. Concatenating immutable sequences always results in a new\n object. This means that building up a sequence by repeated\n concatenation will have a quadratic runtime cost in the total\n sequence length. To get a linear runtime cost, you must switch to\n one of the alternatives below:\n\n * if concatenating "str" objects, you can build a list and use\n "str.join()" at the end or else write to a "io.StringIO" instance\n and retrieve its value when complete\n\n * if concatenating "bytes" objects, you can similarly use\n "bytes.join()" or "io.BytesIO", or you can do in-place\n concatenation with a "bytearray" object. "bytearray" objects are\n mutable and have an efficient overallocation mechanism\n\n * if concatenating "tuple" objects, extend a "list" instead\n\n * for other types, investigate the relevant class documentation\n\n7. Some sequence types (such as "range") only support item\n sequences that follow specific patterns, and hence don\'t support\n sequence concatenation or repetition.\n\n8. "index" raises "ValueError" when *x* is not found in *s*. When\n supported, the additional arguments to the index method allow\n efficient searching of subsections of the sequence. Passing the\n extra arguments is roughly equivalent to using "s[i:j].index(x)",\n only without copying any data and with the returned index being\n relative to the start of the sequence rather than the start of the\n slice.\n\n\nImmutable Sequence Types\n========================\n\nThe only operation that immutable sequence types generally implement\nthat is not also implemented by mutable sequence types is support for\nthe "hash()" built-in.\n\nThis support allows immutable sequences, such as "tuple" instances, to\nbe used as "dict" keys and stored in "set" and "frozenset" instances.\n\nAttempting to hash an immutable sequence that contains unhashable\nvalues will result in "TypeError".\n\n\nMutable Sequence Types\n======================\n\nThe operations in the following table are defined on mutable sequence\ntypes. The "collections.abc.MutableSequence" ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, "bytearray" only\naccepts integers that meet the value restriction "0 <= x <= 255").\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j:k] = t" | the elements of "s[i:j:k]" are | (1) |\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s.clear()" | removes all items from "s" (same | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.copy()" | creates a shallow copy of "s" | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s.pop([i])" | retrieves the item at *i* and | (2) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.remove(x)" | remove the first item from *s* | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.reverse()" | reverses the items of *s* in | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to "-1", so that by default\n the last item is removed and returned.\n\n3. "remove" raises "ValueError" when *x* is not found in *s*.\n\n4. The "reverse()" method modifies the sequence in place for\n economy of space when reversing a large sequence. To remind users\n that it operates by side effect, it does not return the reversed\n sequence.\n\n5. "clear()" and "copy()" are included for consistency with the\n interfaces of mutable containers that don\'t support slicing\n operations (such as "dict" and "set")\n\n New in version 3.3: "clear()" and "copy()" methods.\n\n\nLists\n=====\n\nLists are mutable sequences, typically used to store collections of\nhomogeneous items (where the precise degree of similarity will vary by\napplication).\n\nclass class list([iterable])\n\n Lists may be constructed in several ways:\n\n * Using a pair of square brackets to denote the empty list: "[]"\n\n * Using square brackets, separating items with commas: "[a]",\n "[a, b, c]"\n\n * Using a list comprehension: "[x for x in iterable]"\n\n * Using the type constructor: "list()" or "list(iterable)"\n\n The constructor builds a list whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a list, a copy is made and\n returned, similar to "iterable[:]". For example, "list(\'abc\')"\n returns "[\'a\', \'b\', \'c\']" and "list( (1, 2, 3) )" returns "[1, 2,\n 3]". If no argument is given, the constructor creates a new empty\n list, "[]".\n\n Many other operations also produce lists, including the "sorted()"\n built-in.\n\n Lists implement all of the *common* and *mutable* sequence\n operations. Lists also provide the following additional method:\n\n sort(*, key=None, reverse=None)\n\n This method sorts the list in place, using only "<" comparisons\n between items. Exceptions are not suppressed - if any comparison\n operations fail, the entire sort operation will fail (and the\n list will likely be left in a partially modified state).\n\n "sort()" accepts two arguments that can only be passed by\n keyword (*keyword-only arguments*):\n\n *key* specifies a function of one argument that is used to\n extract a comparison key from each list element (for example,\n "key=str.lower"). The key corresponding to each item in the list\n is calculated once and then used for the entire sorting process.\n The default value of "None" means that list items are sorted\n directly without calculating a separate key value.\n\n The "functools.cmp_to_key()" utility is available to convert a\n 2.x style *cmp* function to a *key* function.\n\n *reverse* is a boolean value. If set to "True", then the list\n elements are sorted as if each comparison were reversed.\n\n This method modifies the sequence in place for economy of space\n when sorting a large sequence. To remind users that it operates\n by side effect, it does not return the sorted sequence (use\n "sorted()" to explicitly request a new sorted list instance).\n\n The "sort()" method is guaranteed to be stable. A sort is\n stable if it guarantees not to change the relative order of\n elements that compare equal --- this is helpful for sorting in\n multiple passes (for example, sort by department, then by salary\n grade).\n\n **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python makes the list appear\n empty for the duration, and raises "ValueError" if it can detect\n that the list has been mutated during a sort.\n\n\nTuples\n======\n\nTuples are immutable sequences, typically used to store collections of\nheterogeneous data (such as the 2-tuples produced by the "enumerate()"\nbuilt-in). Tuples are also used for cases where an immutable sequence\nof homogeneous data is needed (such as allowing storage in a "set" or\n"dict" instance).\n\nclass class tuple([iterable])\n\n Tuples may be constructed in a number of ways:\n\n * Using a pair of parentheses to denote the empty tuple: "()"\n\n * Using a trailing comma for a singleton tuple: "a," or "(a,)"\n\n * Separating items with commas: "a, b, c" or "(a, b, c)"\n\n * Using the "tuple()" built-in: "tuple()" or "tuple(iterable)"\n\n The constructor builds a tuple whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a tuple, it is returned\n unchanged. For example, "tuple(\'abc\')" returns "(\'a\', \'b\', \'c\')"\n and "tuple( [1, 2, 3] )" returns "(1, 2, 3)". If no argument is\n given, the constructor creates a new empty tuple, "()".\n\n Note that it is actually the comma which makes a tuple, not the\n parentheses. The parentheses are optional, except in the empty\n tuple case, or when they are needed to avoid syntactic ambiguity.\n For example, "f(a, b, c)" is a function call with three arguments,\n while "f((a, b, c))" is a function call with a 3-tuple as the sole\n argument.\n\n Tuples implement all of the *common* sequence operations.\n\nFor heterogeneous collections of data where access by name is clearer\nthan access by index, "collections.namedtuple()" may be a more\nappropriate choice than a simple tuple object.\n\n\nRanges\n======\n\nThe "range" type represents an immutable sequence of numbers and is\ncommonly used for looping a specific number of times in "for" loops.\n\nclass class range(stop)\nclass class range(start, stop[, step])\n\n The arguments to the range constructor must be integers (either\n built-in "int" or any object that implements the "__index__"\n special method). If the *step* argument is omitted, it defaults to\n "1". If the *start* argument is omitted, it defaults to "0". If\n *step* is zero, "ValueError" is raised.\n\n For a positive *step*, the contents of a range "r" are determined\n by the formula "r[i] = start + step*i" where "i >= 0" and "r[i] <\n stop".\n\n For a negative *step*, the contents of the range are still\n determined by the formula "r[i] = start + step*i", but the\n constraints are "i >= 0" and "r[i] > stop".\n\n A range object will be empty if "r[0]" does not meet the value\n constraint. Ranges do support negative indices, but these are\n interpreted as indexing from the end of the sequence determined by\n the positive indices.\n\n Ranges containing absolute values larger than "sys.maxsize" are\n permitted but some features (such as "len()") may raise\n "OverflowError".\n\n Range examples:\n\n >>> list(range(10))\n [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n >>> list(range(1, 11))\n [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n >>> list(range(0, 30, 5))\n [0, 5, 10, 15, 20, 25]\n >>> list(range(0, 10, 3))\n [0, 3, 6, 9]\n >>> list(range(0, -10, -1))\n [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]\n >>> list(range(0))\n []\n >>> list(range(1, 0))\n []\n\n Ranges implement all of the *common* sequence operations except\n concatenation and repetition (due to the fact that range objects\n can only represent sequences that follow a strict pattern and\n repetition and concatenation will usually violate that pattern).\n\nThe advantage of the "range" type over a regular "list" or "tuple" is\nthat a "range" object will always take the same (small) amount of\nmemory, no matter the size of the range it represents (as it only\nstores the "start", "stop" and "step" values, calculating individual\nitems and subranges as needed).\n\nRange objects implement the "collections.abc.Sequence" ABC, and\nprovide features such as containment tests, element index lookup,\nslicing and support for negative indices (see *Sequence Types ---\nlist, tuple, range*):\n\n>>> r = range(0, 20, 2)\n>>> r\nrange(0, 20, 2)\n>>> 11 in r\nFalse\n>>> 10 in r\nTrue\n>>> r.index(10)\n5\n>>> r[5]\n10\n>>> r[:5]\nrange(0, 10, 2)\n>>> r[-1]\n18\n\nTesting range objects for equality with "==" and "!=" compares them as\nsequences. That is, two range objects are considered equal if they\nrepresent the same sequence of values. (Note that two range objects\nthat compare equal might have different "start", "stop" and "step"\nattributes, for example "range(0) == range(2, 1, 3)" or "range(0, 3,\n2) == range(0, 4, 2)".)\n\nChanged in version 3.2: Implement the Sequence ABC. Support slicing\nand negative indices. Test "int" objects for membership in constant\ntime instead of iterating through all items.\n\nChanged in version 3.3: Define \'==\' and \'!=\' to compare range objects\nbased on the sequence of values they define (instead of comparing\nbased on object identity).\n\nNew in version 3.3: The "start", "stop" and "step" attributes.\n', + 'typesseq-mutable': '\nMutable Sequence Types\n**********************\n\nThe operations in the following table are defined on mutable sequence\ntypes. The "collections.abc.MutableSequence" ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, "bytearray" only\naccepts integers that meet the value restriction "0 <= x <= 255").\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j:k] = t" | the elements of "s[i:j:k]" are | (1) |\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s.clear()" | removes all items from "s" (same | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.copy()" | creates a shallow copy of "s" | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s.pop([i])" | retrieves the item at *i* and | (2) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.remove(x)" | remove the first item from *s* | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.reverse()" | reverses the items of *s* in | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to "-1", so that by default\n the last item is removed and returned.\n\n3. "remove" raises "ValueError" when *x* is not found in *s*.\n\n4. The "reverse()" method modifies the sequence in place for\n economy of space when reversing a large sequence. To remind users\n that it operates by side effect, it does not return the reversed\n sequence.\n\n5. "clear()" and "copy()" are included for consistency with the\n interfaces of mutable containers that don\'t support slicing\n operations (such as "dict" and "set")\n\n New in version 3.3: "clear()" and "copy()" methods.\n', + 'unary': '\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary "-" (minus) operator yields the negation of its numeric\nargument.\n\nThe unary "+" (plus) operator yields its numeric argument unchanged.\n\nThe unary "~" (invert) operator yields the bitwise inversion of its\ninteger argument. The bitwise inversion of "x" is defined as\n"-(x+1)". It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n"TypeError" exception is raised.\n', + 'while': '\nThe "while" statement\n*********************\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n', + 'with': '\nThe "with" statement\n********************\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', + 'yield': '\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nThe "yield" statement is only used when defining a generator function,\nand is only used in the body of the generator function. Using a\n"yield" statement in a function definition is sufficient to cause that\ndefinition to create a generator function instead of a normal\nfunction.\n\nWhen a generator function is called, it returns an iterator known as a\ngenerator iterator, or more commonly, a generator. The body of the\ngenerator function is executed by calling the "next()" function on the\ngenerator repeatedly until it raises an exception.\n\nWhen a "yield" statement is executed, the state of the generator is\nfrozen and the value of "expression_list" is returned to "next()"\'s\ncaller. By "frozen" we mean that all local state is retained,\nincluding the current bindings of local variables, the instruction\npointer, and the internal evaluation stack: enough information is\nsaved so that the next time "next()" is invoked, the function can\nproceed exactly as if the "yield" statement were just another external\ncall.\n\nThe "yield" statement is allowed in the "try" clause of a "try" ...\n"finally" construct. If the generator is not resumed before it is\nfinalized (by reaching a zero reference count or by being garbage\ncollected), the generator-iterator\'s "close()" method will be called,\nallowing any pending "finally" clauses to execute.\n\nWhen "yield from " is used, it treats the supplied expression as\na subiterator, producing values from it until the underlying iterator\nis exhausted.\n\n Changed in version 3.3: Added "yield from " to delegate\n control flow to a subiterator\n\nFor full details of "yield" semantics, refer to the *Yield\nexpressions* section.\n\nSee also: **PEP 0255** - Simple Generators\n\n The proposal for adding generators and the "yield" statement to\n Python.\n\n **PEP 0342** - Coroutines via Enhanced Generators\n The proposal to enhance the API and syntax of generators, making\n them usable as simple coroutines.\n\n **PEP 0380** - Syntax for Delegating to a Subgenerator\n The proposal to introduce the "yield_from" syntax, making\n delegation to sub-generators easy.\n'} -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:04:49 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:04:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Update_IDLE_ne?= =?utf-8?q?ws_from_Misc/NEWS=2E?= Message-ID: <3fNKPY39cdz7Lk7@mail.python.org> http://hg.python.org/cpython/rev/25c2aa95ebb5 changeset: 89107:25c2aa95ebb5 branch: 3.3 user: Georg Brandl date: Sat Jan 25 09:19:36 2014 +0100 summary: Update IDLE news from Misc/NEWS. files: Lib/idlelib/NEWS.txt | 62 ++++++++++++++++++++++++++++++++ 1 files changed, 62 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,3 +1,65 @@ +What's New in IDLE 3.3.4? +========================= + +- Issue #17390: Add Python version to Idle editor window title bar. + Original patches by Edmond Burnett and Kent Johnson. + +- Issue #18960: IDLE now ignores the source encoding declaration on the second + line if the first line contains anything except a comment. + +- Issue #20058: sys.stdin.readline() in IDLE now always returns only one line. + +- Issue #19481: print() of string subclass instance in IDLE no longer hangs. + +- Issue #18270: Prevent possible IDLE AttributeError on OS X when no initial + shell window is present. + + +What's New in IDLE 3.3.3? +========================= + +- Issue #18873: IDLE now detects Python source code encoding only in comment + lines. + +- Issue #18988: The "Tab" key now works when a word is already autocompleted. + +- Issue #18489: Add tests for SearchEngine. Original patch by Phil Webster. + +- Issue #18429: Format / Format Paragraph, now works when comment blocks + are selected. As with text blocks, this works best when the selection + only includes complete lines. + +- Issue #18226: Add docstrings and unittests for FormatParagraph.py. + Original patches by Todd Rovito and Phil Webster. + +- Issue #18279: Format - Strip trailing whitespace no longer marks a file as + changed when it has not been changed. This fix followed the addition of a + test file originally written by Phil Webster (the issue's main goal). + +- Issue #7136: In the Idle File menu, "New Window" is renamed "New File". + Patch by Tal Einat, Roget Serwy, and Todd Rovito. + +- Remove dead imports of imp. + +- Issue #18196: Avoid displaying spurious SystemExit tracebacks. + +- Issue #5492: Avoid traceback when exiting IDLE caused by a race condition. + +- Issue #17511: Keep IDLE find dialog open after clicking "Find Next". + Original patch by Sarah K. + +- Issue #18055: Move IDLE off of imp and on to importlib. + +- Issue #15392: Create a unittest framework for IDLE. + Initial patch by Rajagopalasarma Jayakrishnan. + See Lib/idlelib/idle_test/README.txt for how to run Idle tests. + +- Issue #14146: Highlight source line while debugging on Windows. + +- Issue #17532: Always include Options menu for IDLE on OS X. + Patch by Guilherme Sim?es. + + What's New in IDLE 3.3.2? ========================= -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:04:50 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:04:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogQnVtcCB0byAzLjMu?= =?utf-8?q?4rc1=2E?= Message-ID: <3fNKPZ6Vh9z7Ljb@mail.python.org> http://hg.python.org/cpython/rev/7f32e55f161b changeset: 89108:7f32e55f161b branch: 3.3 user: Georg Brandl date: Sat Jan 25 09:19:50 2014 +0100 summary: Bump to 3.3.4rc1. files: Include/patchlevel.h | 8 ++++---- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 4 ++-- Misc/RPM/python-3.3.spec | 2 +- README | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 3 -#define PY_MICRO_VERSION 3 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL -#define PY_RELEASE_SERIAL 0 +#define PY_MICRO_VERSION 4 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.3.3+" +#define PY_VERSION "3.3.4rc1" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.3.3" +__version__ = "3.3.4rc1" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.3.3" +IDLE_VERSION = "3.3.4rc1" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,7 +5,7 @@ What's New in Python 3.3.4 release candidate 1? =============================================== -*Not yet released, see sections below for changes released in 3.3.3* +*Release date: 26-Jan-2014* Core and Builtins ----------------- @@ -275,7 +275,7 @@ IDLE ---- ---Issue #17390: Add Python version to Idle editor window title bar. +- Issue #17390: Add Python version to Idle editor window title bar. Original patches by Edmond Burnett and Kent Johnson. - Issue #18960: IDLE now ignores the source encoding declaration on the second diff --git a/Misc/RPM/python-3.3.spec b/Misc/RPM/python-3.3.spec --- a/Misc/RPM/python-3.3.spec +++ b/Misc/RPM/python-3.3.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.3.3 +%define version 3.3.4rc1 %define libvers 3.3 #--end constants-- %define release 1pydotorg diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.3.3 -============================ +This is Python version 3.3.4 release candidate 1 +================================================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Python Software Foundation. All rights reserved. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:04:52 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:04:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Added_tag_v3?= =?utf-8?q?=2E3=2E4rc1_for_changeset_7f32e55f161b?= Message-ID: <3fNKPc2QbSz7LjR@mail.python.org> http://hg.python.org/cpython/rev/40eac0c035e9 changeset: 89109:40eac0c035e9 branch: 3.3 user: Georg Brandl date: Sat Jan 25 09:49:22 2014 +0100 summary: Added tag v3.3.4rc1 for changeset 7f32e55f161b files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -118,3 +118,4 @@ fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 +7f32e55f161b6fe925b6c413907621a8abec71f5 v3.3.4rc1 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:04:53 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:04:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogQ2xvc2VzICMxOTk2?= =?utf-8?q?6=3A_allow_hgtouch_to_operate_on_a_base_dir_that_is_!=3D_the_re?= =?utf-8?q?po_root=2E?= Message-ID: <3fNKPd5nSNz7Ljt@mail.python.org> http://hg.python.org/cpython/rev/ab0b9107628f changeset: 89110:ab0b9107628f branch: 3.3 user: Georg Brandl date: Mon Jan 27 08:22:49 2014 +0100 summary: Closes #19966: allow hgtouch to operate on a base dir that is != the repo root. files: Tools/hg/hgtouch.py | 35 +++++++++++++++++++++----------- 1 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Tools/hg/hgtouch.py b/Tools/hg/hgtouch.py --- a/Tools/hg/hgtouch.py +++ b/Tools/hg/hgtouch.py @@ -36,12 +36,16 @@ result[o] = inputs return result -def check_rule(ui, repo, modified, output, inputs): +def check_rule(ui, repo, modified, basedir, output, inputs): """Verify that the output is newer than any of the inputs. Return (status, stamp), where status is True if the update succeeded, and stamp is the newest time stamp assigned to any file (might be in - the future).""" - f_output = repo.wjoin(output) + the future). + + If basedir is nonempty, it gives a directory in which the tree is to + be checked. + """ + f_output = repo.wjoin(os.path.join(basedir, output)) try: o_time = os.stat(f_output).st_mtime except OSError: @@ -51,7 +55,7 @@ backdate = None backdate_source = None for i in inputs: - f_i = repo.wjoin(i) + f_i = repo.wjoin(os.path.join(basedir, i)) try: i_time = os.stat(f_i).st_mtime except OSError: @@ -79,8 +83,14 @@ # Nothing to update return True, 0 -def do_touch(ui, repo): - modified = repo.status()[0] +def do_touch(ui, repo, basedir): + if basedir: + if not os.path.isdir(repo.wjoin(basedir)): + ui.warn("Abort: basedir %r does not exist\n" % basedir) + return + modified = [] + else: + modified = repo.status()[0] dependencies = parse_config(repo) success = True tstamp = 0 # newest time stamp assigned @@ -93,8 +103,8 @@ if i in dependencies: hold_back[output] = inputs continue - _success, _tstamp = check_rule(ui, repo, modified, output, inputs) - sucess = success and _success + _success, _tstamp = check_rule(ui, repo, modified, basedir, output, inputs) + success = success and _success tstamp = max(tstamp, _tstamp) # put back held back rules dependencies.update(hold_back) @@ -109,11 +119,12 @@ return False return success -def touch(ui, repo): +def touch(ui, repo, basedir): "touch generated files that are older than their sources after an update." - do_touch(ui, repo) + do_touch(ui, repo, basedir) cmdtable = { - "touch": (touch, [], - "touch generated files according to the .hgtouch configuration") + "touch": (touch, + [('b', 'basedir', '', 'base dir of the tree to apply touching', 'BASEDIR')], + "hg touch [-b BASEDIR]") } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:04:55 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:04:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogLmhndG91Y2g6IGFk?= =?utf-8?q?d_a_rule_for_Include/Python-ast=2Eh?= Message-ID: <3fNKPg5xv8z7Lk5@mail.python.org> http://hg.python.org/cpython/rev/0630833d474c changeset: 89111:0630833d474c branch: 3.3 user: Georg Brandl date: Mon Jan 27 07:56:59 2014 +0100 summary: .hgtouch: add a rule for Include/Python-ast.h files: .hgtouch | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/.hgtouch b/.hgtouch --- a/.hgtouch +++ b/.hgtouch @@ -5,7 +5,8 @@ Python/importlib.h: Lib/importlib/_bootstrap.py Modules/_freeze_importlib.c Include/ast.h: Parser/Python.asdl Parser/asdl.py Parser/asdl_c.py -Python/Python-ast.c: Include/ast.h +Include/Python-ast.h: Include/ast.h +Python/Python-ast.c: Include/Python-ast.h Python/opcode_targets.h: Python/makeopcodetargets.py Lib/opcode.py -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:04:57 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:04:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Remove_old_tag?= =?utf-8?q?=2E?= Message-ID: <3fNKPj2GdFz7LkN@mail.python.org> http://hg.python.org/cpython/rev/fa92f5f940c6 changeset: 89112:fa92f5f940c6 branch: 3.3 tag: v3.3.4rc1 user: Georg Brandl date: Mon Jan 27 08:24:02 2014 +0100 summary: Remove old tag. files: .hgtags | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -118,4 +118,3 @@ fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 -7f32e55f161b6fe925b6c413907621a8abec71f5 v3.3.4rc1 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:04:58 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:04:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Added_tag_v3?= =?utf-8?q?=2E3=2E4rc1_for_changeset_fa92f5f940c6?= Message-ID: <3fNKPk5k6qz7LkH@mail.python.org> http://hg.python.org/cpython/rev/049aab1f7cb6 changeset: 89113:049aab1f7cb6 branch: 3.3 user: Georg Brandl date: Mon Jan 27 08:24:09 2014 +0100 summary: Added tag v3.3.4rc1 for changeset fa92f5f940c6 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -118,3 +118,4 @@ fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 +fa92f5f940c6c0d839d7f0611e4b717606504a3c v3.3.4rc1 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:05:00 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:05:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Post_release_u?= =?utf-8?q?pdate=2E?= Message-ID: <3fNKPm1zNqz7LjM@mail.python.org> http://hg.python.org/cpython/rev/753b8c4d792e changeset: 89114:753b8c4d792e branch: 3.3 user: Georg Brandl date: Mon Jan 27 08:35:20 2014 +0100 summary: Post release update. files: Include/patchlevel.h | 2 +- Misc/NEWS | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.3.4rc1" +#define PY_VERSION "3.3.4rc1+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.3.4? +=========================== + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.3.4 release candidate 1? =============================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:05:01 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:05:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogQnVtcCB0byAzLjMu?= =?utf-8?q?4_final?= Message-ID: <3fNKPn51ykz7LjZ@mail.python.org> http://hg.python.org/cpython/rev/3d9a0e780035 changeset: 89115:3d9a0e780035 branch: 3.3 user: Georg Brandl date: Sun Feb 09 08:43:05 2014 +0100 summary: Bump to 3.3.4 final files: Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 10 +++------- Misc/RPM/python-3.3.spec | 2 +- README | 4 ++-- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -19,11 +19,11 @@ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 3 #define PY_MICRO_VERSION 4 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.3.4rc1+" +#define PY_VERSION "3.3.4" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.3.4rc1" +__version__ = "3.3.4" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.3.4rc1" +IDLE_VERSION = "3.3.4" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,13 +5,9 @@ What's New in Python 3.3.4? =========================== -*Release date: XXXX-XX-XX* - -Core and Builtins ------------------ - -Library -------- +*Release date: 09-Feb-2014* + +No changes relative to rc1. What's New in Python 3.3.4 release candidate 1? diff --git a/Misc/RPM/python-3.3.spec b/Misc/RPM/python-3.3.spec --- a/Misc/RPM/python-3.3.spec +++ b/Misc/RPM/python-3.3.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.3.4rc1 +%define version 3.3.4 %define libvers 3.3 #--end constants-- %define release 1pydotorg diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.3.4 release candidate 1 -================================================ +This is Python version 3.3.4 +============================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Python Software Foundation. All rights reserved. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:05:03 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:05:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwMzc0?= =?utf-8?q?=3A_Avoid_compiler_warnings_when_compiling_readline_with_libedi?= =?utf-8?q?t=2E?= Message-ID: <3fNKPq26Khz7LkR@mail.python.org> http://hg.python.org/cpython/rev/a7e048674fef changeset: 89116:a7e048674fef branch: 3.3 user: Ned Deily date: Wed Feb 05 16:53:10 2014 -0800 summary: Issue #20374: Avoid compiler warnings when compiling readline with libedit. files: Modules/readline.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -773,15 +773,24 @@ return result; } + static int +#if defined(_RL_FUNCTION_TYPEDEF) on_startup_hook(void) +#else +on_startup_hook() +#endif { return on_hook(startup_hook); } #ifdef HAVE_RL_PRE_INPUT_HOOK static int +#if defined(_RL_FUNCTION_TYPEDEF) on_pre_input_hook(void) +#else +on_pre_input_hook() +#endif { return on_hook(pre_input_hook); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:05:05 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:05:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwMzc0?= =?utf-8?q?=3A_delete_spurious_empty_line?= Message-ID: <3fNKPs3h7Zz7Ljb@mail.python.org> http://hg.python.org/cpython/rev/de02d414590d changeset: 89117:de02d414590d branch: 3.3 user: Ned Deily date: Wed Feb 05 17:02:29 2014 -0800 summary: Issue #20374: delete spurious empty line files: Modules/readline.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -773,7 +773,6 @@ return result; } - static int #if defined(_RL_FUNCTION_TYPEDEF) on_startup_hook(void) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:05:06 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:05:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_news_entry?= Message-ID: <3fNKPt6r3Pz7LkZ@mail.python.org> http://hg.python.org/cpython/rev/7ff62415e426 changeset: 89118:7ff62415e426 branch: 3.3 tag: v3.3.4 user: Georg Brandl date: Sun Feb 09 08:57:59 2014 +0100 summary: news entry files: Misc/NEWS | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -7,7 +7,10 @@ *Release date: 09-Feb-2014* -No changes relative to rc1. +Library +------- + +- Issue #20374: Fix build warnings of the readline module with libedit on Mac. What's New in Python 3.3.4 release candidate 1? -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:05:09 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:05:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Added_tag_v3?= =?utf-8?q?=2E3=2E4_for_changeset_7ff62415e426?= Message-ID: <3fNKPx2V3Lz7Lkd@mail.python.org> http://hg.python.org/cpython/rev/318a642a96c1 changeset: 89119:318a642a96c1 branch: 3.3 user: Georg Brandl date: Sun Feb 09 08:59:00 2014 +0100 summary: Added tag v3.3.4 for changeset 7ff62415e426 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -119,3 +119,4 @@ d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 fa92f5f940c6c0d839d7f0611e4b717606504a3c v3.3.4rc1 +7ff62415e4263c432c8acf6e424224209211eadb v3.3.4 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:05:10 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:05:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Post-release_u?= =?utf-8?q?pdates=2E?= Message-ID: <3fNKPy4nTMz7Lkk@mail.python.org> http://hg.python.org/cpython/rev/7b50a0badcef changeset: 89120:7b50a0badcef branch: 3.3 user: Georg Brandl date: Mon Feb 10 21:56:33 2014 +0100 summary: Post-release updates. files: Include/patchlevel.h | 2 +- Misc/NEWS | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.3.4" +#define PY_VERSION "3.3.4+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.3.5 release candidate 1? +=============================================== + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.3.4? =========================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:05:15 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:05:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuMyk6?= =?utf-8?q?_merge_with_3=2E3=2E4_releasing_repo?= Message-ID: <3fNKQ32MwGz7Ljr@mail.python.org> http://hg.python.org/cpython/rev/5c473ae503e8 changeset: 89121:5c473ae503e8 branch: 3.3 parent: 89100:79a6300f6421 parent: 89120:7b50a0badcef user: Georg Brandl date: Mon Feb 10 22:04:20 2014 +0100 summary: merge with 3.3.4 releasing repo files: .hgtags | 2 + .hgtouch | 3 +- Doc/tools/sphinxext/susp-ignored.csv | 1 + Include/patchlevel.h | 4 +- Lib/distutils/__init__.py | 2 +- Lib/idlelib/NEWS.txt | 62 ++++ Lib/idlelib/idlever.py | 2 +- Lib/pydoc_data/topics.py | 148 +++++----- Lib/smtplib.py | 5 +- Lib/test/mock_socket.py | 9 +- Lib/test/test_smtplib.py | 30 ++- Misc/NEWS | 209 ++++++++------ Misc/RPM/python-3.3.spec | 2 +- README | 2 +- Tools/hg/hgtouch.py | 35 +- 15 files changed, 332 insertions(+), 184 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -118,3 +118,5 @@ fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 +fa92f5f940c6c0d839d7f0611e4b717606504a3c v3.3.4rc1 +7ff62415e4263c432c8acf6e424224209211eadb v3.3.4 diff --git a/.hgtouch b/.hgtouch --- a/.hgtouch +++ b/.hgtouch @@ -5,7 +5,8 @@ Python/importlib.h: Lib/importlib/_bootstrap.py Modules/_freeze_importlib.c Include/ast.h: Parser/Python.asdl Parser/asdl.py Parser/asdl_c.py -Python/Python-ast.c: Include/ast.h +Include/Python-ast.h: Include/ast.h +Python/Python-ast.c: Include/Python-ast.h Python/opcode_targets.h: Python/makeopcodetargets.py Lib/opcode.py diff --git a/Doc/tools/sphinxext/susp-ignored.csv b/Doc/tools/sphinxext/susp-ignored.csv --- a/Doc/tools/sphinxext/susp-ignored.csv +++ b/Doc/tools/sphinxext/susp-ignored.csv @@ -287,3 +287,4 @@ whatsnew/changelog,,::,": Fix FTP tests for IPv6, bind to ""::1"" instead of ""localhost""." whatsnew/changelog,,::,": Use ""127.0.0.1"" or ""::1"" instead of ""localhost"" as much as" whatsnew/changelog,,:password,user:password +whatsnew/changelog,,:gz,w:gz diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 3 -#define PY_MICRO_VERSION 3 +#define PY_MICRO_VERSION 4 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "3.3.3+" +#define PY_VERSION "3.3.4+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.3.3" +__version__ = "3.3.4" #--end constants-- diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,3 +1,65 @@ +What's New in IDLE 3.3.4? +========================= + +- Issue #17390: Add Python version to Idle editor window title bar. + Original patches by Edmond Burnett and Kent Johnson. + +- Issue #18960: IDLE now ignores the source encoding declaration on the second + line if the first line contains anything except a comment. + +- Issue #20058: sys.stdin.readline() in IDLE now always returns only one line. + +- Issue #19481: print() of string subclass instance in IDLE no longer hangs. + +- Issue #18270: Prevent possible IDLE AttributeError on OS X when no initial + shell window is present. + + +What's New in IDLE 3.3.3? +========================= + +- Issue #18873: IDLE now detects Python source code encoding only in comment + lines. + +- Issue #18988: The "Tab" key now works when a word is already autocompleted. + +- Issue #18489: Add tests for SearchEngine. Original patch by Phil Webster. + +- Issue #18429: Format / Format Paragraph, now works when comment blocks + are selected. As with text blocks, this works best when the selection + only includes complete lines. + +- Issue #18226: Add docstrings and unittests for FormatParagraph.py. + Original patches by Todd Rovito and Phil Webster. + +- Issue #18279: Format - Strip trailing whitespace no longer marks a file as + changed when it has not been changed. This fix followed the addition of a + test file originally written by Phil Webster (the issue's main goal). + +- Issue #7136: In the Idle File menu, "New Window" is renamed "New File". + Patch by Tal Einat, Roget Serwy, and Todd Rovito. + +- Remove dead imports of imp. + +- Issue #18196: Avoid displaying spurious SystemExit tracebacks. + +- Issue #5492: Avoid traceback when exiting IDLE caused by a race condition. + +- Issue #17511: Keep IDLE find dialog open after clicking "Find Next". + Original patch by Sarah K. + +- Issue #18055: Move IDLE off of imp and on to importlib. + +- Issue #15392: Create a unittest framework for IDLE. + Initial patch by Rajagopalasarma Jayakrishnan. + See Lib/idlelib/idle_test/README.txt for how to run Idle tests. + +- Issue #14146: Highlight source line while debugging on Windows. + +- Issue #17532: Always include Options menu for IDLE on OS X. + Patch by Guilherme Sim?es. + + What's New in IDLE 3.3.2? ========================= diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.3.3" +IDLE_VERSION = "3.3.4" diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,79 +1,79 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sun Oct 27 09:07:55 2013 -topics = {'assert': '\nThe ``assert`` statement\n************************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, ``assert expression``, is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, ``assert expression1, expression2``, is equivalent\nto\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that ``__debug__`` and ``AssertionError``\nrefer to the built-in variables with those names. In the current\nimplementation, the built-in variable ``__debug__`` is ``True`` under\nnormal circumstances, ``False`` when optimization is requested\n(command line option -O). The current code generator emits no code\nfor an assert statement when optimization is requested at compile\ntime. Note that it is unnecessary to include the source code for the\nexpression that failed in the error message; it will be displayed as\npart of the stack trace.\n\nAssignments to ``__debug__`` are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', - 'assignment': '\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The object\n must be an iterable with the same number of items as there are\n targets in the target list, and the items are assigned, from left to\n right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an asterisk,\n called a "starred" target: The object must be a sequence with at\n least as many items as there are targets in the target list, minus\n one. The first items of the sequence are assigned, from left to\n right, to the targets before the starred target. The final items\n of the sequence are assigned to the targets after the starred\n target. A list of the remaining items in the sequence is then\n assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of items\n as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a ``global`` or ``nonlocal``\n statement in the current code block: the name is bound to the\n object in the current local namespace.\n\n * Otherwise: the name is bound to the object in the global namespace\n or the outer namespace determined by ``nonlocal``, respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in square\n brackets: The object must be an iterable with the same number of\n items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, ``TypeError`` is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily ``AttributeError``).\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n ``a.x`` can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target ``a.x`` is\n always set as an instance attribute, creating it if necessary.\n Thus, the two occurrences of ``a.x`` do not necessarily refer to the\n same attribute: if the RHS expression refers to a class attribute,\n the LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with ``property()``.\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, ``IndexError`` is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the ``__setitem__()`` method is called\n with appropriate arguments.\n\n* If the target is a slicing: The primary expression in the reference\n is evaluated. It should yield a mutable sequence object (such as a\n list). The assigned object should be a sequence object of the same\n type. Next, the lower and upper bound expressions are evaluated,\n insofar they are present; defaults are zero and the sequence\'s\n length. The bounds should evaluate to integers. If either bound is\n negative, the sequence\'s length is added to it. The resulting\n bounds are clipped to lie between zero and the sequence\'s length,\n inclusive. Finally, the sequence object is asked to replace the\n slice with the items of the assigned sequence. The length of the\n slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample ``a, b = b, a`` swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints ``[0, 2]``:\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print(x)\n\nSee also:\n\n **PEP 3132** - Extended Iterable Unpacking\n The specification for the ``*target`` feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like ``x += 1`` can be rewritten as\n``x = x + 1`` to achieve a similar, but not exactly equal effect. In\nthe augmented version, ``x`` is only evaluated once. Also, when\npossible, the actual operation is performed *in-place*, meaning that\nrather than creating a new object and assigning that to the target,\nthe old object is modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', - 'atom-identifiers': '\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a ``NameError`` exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier\n``__spam`` occurring in a class named ``Ham`` will be transformed to\n``_Ham__spam``. This transformation is independent of the syntactical\ncontext in which the identifier is used. If the transformed name is\nextremely long (longer than 255 characters), implementation defined\ntruncation may happen. If the class name consists only of underscores,\nno transformation is done.\n', +# Autogenerated by Sphinx on Sat Jan 25 09:13:25 2014 +topics = {'assert': '\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', + 'assignment': '\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints "[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', + 'atom-identifiers': '\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', 'atom-literals': "\nLiterals\n********\n\nPython supports string and bytes literals and various numeric\nliterals:\n\n literal ::= stringliteral | bytesliteral\n | integer | floatnumber | imagnumber\n\nEvaluation of a literal yields an object of the given type (string,\nbytes, integer, floating point number, complex number) with the given\nvalue. The value may be approximated in the case of floating point\nand imaginary (complex) literals. See section *Literals* for details.\n\nAll literals correspond to immutable data types, and hence the\nobject's identity is less important than its value. Multiple\nevaluations of literals with the same value (either the same\noccurrence in the program text or a different occurrence) may obtain\nthe same object or a different object with the same value.\n", - 'attribute-access': '\nCustomizing attribute access\n****************************\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of ``x.name``)\nfor class instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for ``self``). ``name`` is the attribute name.\n This method should return the (computed) attribute value or raise\n an ``AttributeError`` exception.\n\n Note that if the attribute is found through the normal mechanism,\n ``__getattr__()`` is not called. (This is an intentional asymmetry\n between ``__getattr__()`` and ``__setattr__()``.) This is done both\n for efficiency reasons and because otherwise ``__getattr__()``\n would have no way to access other attributes of the instance. Note\n that at least for instance variables, you can fake total control by\n not inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n ``__getattribute__()`` method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines\n ``__getattr__()``, the latter will not be called unless\n ``__getattribute__()`` either calls it explicitly or raises an\n ``AttributeError``. This method should return the (computed)\n attribute value or raise an ``AttributeError`` exception. In order\n to avoid infinite recursion in this method, its implementation\n should always call the base class method with the same name to\n access any attributes it needs, for example,\n ``object.__getattribute__(self, name)``.\n\n Note: This method may still be bypassed when looking up special methods\n as the result of implicit invocation via language syntax or\n built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If ``__setattr__()`` wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n ``object.__setattr__(self, name, value)``.\n\nobject.__delattr__(self, name)\n\n Like ``__setattr__()`` but for attribute deletion instead of\n assignment. This should only be implemented if ``del obj.name`` is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when ``dir()`` is called on the object. A sequence must be\n returned. ``dir()`` converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n========================\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' ``__dict__``.\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or ``None`` when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an\n ``AttributeError`` exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n====================\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: ``__get__()``, ``__set__()``, and\n``__delete__()``. If any of those methods are defined for an object,\nit is said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, ``a.x`` has a\nlookup chain starting with ``a.__dict__[\'x\']``, then\n``type(a).__dict__[\'x\']``, and continuing through the base classes of\n``type(a)`` excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, ``a.x``.\nHow the arguments are assembled depends on ``a``:\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: ``x.__get__(a)``.\n\nInstance Binding\n If binding to an object instance, ``a.x`` is transformed into the\n call: ``type(a).__dict__[\'x\'].__get__(a, type(a))``.\n\nClass Binding\n If binding to a class, ``A.x`` is transformed into the call:\n ``A.__dict__[\'x\'].__get__(None, A)``.\n\nSuper Binding\n If ``a`` is an instance of ``super``, then the binding ``super(B,\n obj).m()`` searches ``obj.__class__.__mro__`` for the base class\n ``A`` immediately preceding ``B`` and then invokes the descriptor\n with the call: ``A.__dict__[\'m\'].__get__(obj, obj.__class__)``.\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of ``__get__()``, ``__set__()`` and ``__delete__()``.\nIf it does not define ``__get__()``, then accessing the attribute will\nreturn the descriptor object itself unless there is a value in the\nobject\'s instance dictionary. If the descriptor defines ``__set__()``\nand/or ``__delete__()``, it is a data descriptor; if it defines\nneither, it is a non-data descriptor. Normally, data descriptors\ndefine both ``__get__()`` and ``__set__()``, while non-data\ndescriptors have just the ``__get__()`` method. Data descriptors with\n``__set__()`` and ``__get__()`` defined always override a redefinition\nin an instance dictionary. In contrast, non-data descriptors can be\noverridden by instances.\n\nPython methods (including ``staticmethod()`` and ``classmethod()``)\nare implemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe ``property()`` function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n=========\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n class, *__slots__* reserves space for the declared variables and\n prevents the automatic creation of *__dict__* and *__weakref__* for\n each instance.\n\n\nNotes on using *__slots__*\n--------------------------\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises ``AttributeError``. If\n dynamic assignment of new variables is desired, then add\n ``\'__dict__\'`` to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes defining\n *__slots__* do not support weak references to its instances. If weak\n reference support is needed, then add ``\'__weakref__\'`` to the\n sequence of strings in the *__slots__* declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the instance\n variable defined by the base class slot is inaccessible (except by\n retrieving its descriptor directly from the base class). This\n renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as ``int``, ``str`` and\n ``tuple``.\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings may\n also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n', - 'attribute-references': '\nAttribute references\n********************\n\nAn attribute reference is a primary followed by a period and a name:\n\n attributeref ::= primary "." identifier\n\nThe primary must evaluate to an object of a type that supports\nattribute references, which most objects do. This object is then\nasked to produce the attribute whose name is the identifier (which can\nbe customized by overriding the ``__getattr__()`` method). If this\nattribute is not available, the exception ``AttributeError`` is\nraised. Otherwise, the type and value of the object produced is\ndetermined by the object. Multiple evaluations of the same attribute\nreference may yield different objects.\n', - 'augassign': '\nAugmented assignment statements\n*******************************\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like ``x += 1`` can be rewritten as\n``x = x + 1`` to achieve a similar, but not exactly equal effect. In\nthe augmented version, ``x`` is only evaluated once. Also, when\npossible, the actual operation is performed *in-place*, meaning that\nrather than creating a new object and assigning that to the target,\nthe old object is modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', - 'binary': '\nBinary arithmetic operations\n****************************\n\nThe binary arithmetic operations have the conventional priority\nlevels. Note that some of these operations also apply to certain non-\nnumeric types. Apart from the power operator, there are only two\nlevels, one for multiplicative operators and one for additive\noperators:\n\n m_expr ::= u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr\n | m_expr "%" u_expr\n a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr\n\nThe ``*`` (multiplication) operator yields the product of its\narguments. The arguments must either both be numbers, or one argument\nmust be an integer and the other must be a sequence. In the former\ncase, the numbers are converted to a common type and then multiplied\ntogether. In the latter case, sequence repetition is performed; a\nnegative repetition factor yields an empty sequence.\n\nThe ``/`` (division) and ``//`` (floor division) operators yield the\nquotient of their arguments. The numeric arguments are first\nconverted to a common type. Division of integers yields a float, while\nfloor division of integers results in an integer; the result is that\nof mathematical division with the \'floor\' function applied to the\nresult. Division by zero raises the ``ZeroDivisionError`` exception.\n\nThe ``%`` (modulo) operator yields the remainder from the division of\nthe first argument by the second. The numeric arguments are first\nconverted to a common type. A zero right argument raises the\n``ZeroDivisionError`` exception. The arguments may be floating point\nnumbers, e.g., ``3.14%0.7`` equals ``0.34`` (since ``3.14`` equals\n``4*0.7 + 0.34``.) The modulo operator always yields a result with\nthe same sign as its second operand (or zero); the absolute value of\nthe result is strictly smaller than the absolute value of the second\noperand [1].\n\nThe floor division and modulo operators are connected by the following\nidentity: ``x == (x//y)*y + (x%y)``. Floor division and modulo are\nalso connected with the built-in function ``divmod()``: ``divmod(x, y)\n== (x//y, x%y)``. [2].\n\nIn addition to performing the modulo operation on numbers, the ``%``\noperator is also overloaded by string objects to perform old-style\nstring formatting (also known as interpolation). The syntax for\nstring formatting is described in the Python Library Reference,\nsection *printf-style String Formatting*.\n\nThe floor division operator, the modulo operator, and the ``divmod()``\nfunction are not defined for complex numbers. Instead, convert to a\nfloating point number using the ``abs()`` function if appropriate.\n\nThe ``+`` (addition) operator yields the sum of its arguments. The\narguments must either both be numbers or both sequences of the same\ntype. In the former case, the numbers are converted to a common type\nand then added together. In the latter case, the sequences are\nconcatenated.\n\nThe ``-`` (subtraction) operator yields the difference of its\narguments. The numeric arguments are first converted to a common\ntype.\n', - 'bitwise': '\nBinary bitwise operations\n*************************\n\nEach of the three bitwise operations has a different priority level:\n\n and_expr ::= shift_expr | and_expr "&" shift_expr\n xor_expr ::= and_expr | xor_expr "^" and_expr\n or_expr ::= xor_expr | or_expr "|" xor_expr\n\nThe ``&`` operator yields the bitwise AND of its arguments, which must\nbe integers.\n\nThe ``^`` operator yields the bitwise XOR (exclusive OR) of its\narguments, which must be integers.\n\nThe ``|`` operator yields the bitwise (inclusive) OR of its arguments,\nwhich must be integers.\n', - 'bltin-code-objects': '\nCode Objects\n************\n\nCode objects are used by the implementation to represent "pseudo-\ncompiled" executable Python code such as a function body. They differ\nfrom function objects because they don\'t contain a reference to their\nglobal execution environment. Code objects are returned by the built-\nin ``compile()`` function and can be extracted from function objects\nthrough their ``__code__`` attribute. See also the ``code`` module.\n\nA code object can be executed or evaluated by passing it (instead of a\nsource string) to the ``exec()`` or ``eval()`` built-in functions.\n\nSee *The standard type hierarchy* for more information.\n', - 'bltin-ellipsis-object': '\nThe Ellipsis Object\n*******************\n\nThis object is commonly used by slicing (see *Slicings*). It supports\nno special operations. There is exactly one ellipsis object, named\n``Ellipsis`` (a built-in name). ``type(Ellipsis)()`` produces the\n``Ellipsis`` singleton.\n\nIt is written as ``Ellipsis`` or ``...``.\n', - 'bltin-null-object': "\nThe Null Object\n***************\n\nThis object is returned by functions that don't explicitly return a\nvalue. It supports no special operations. There is exactly one null\nobject, named ``None`` (a built-in name). ``type(None)()`` produces\nthe same singleton.\n\nIt is written as ``None``.\n", - 'bltin-type-objects': "\nType Objects\n************\n\nType objects represent the various object types. An object's type is\naccessed by the built-in function ``type()``. There are no special\noperations on types. The standard module ``types`` defines names for\nall standard built-in types.\n\nTypes are written like this: ````.\n", - 'booleans': '\nBoolean operations\n******************\n\n or_test ::= and_test | or_test "or" and_test\n and_test ::= not_test | and_test "and" not_test\n not_test ::= comparison | "not" not_test\n\nIn the context of Boolean operations, and also when expressions are\nused by control flow statements, the following values are interpreted\nas false: ``False``, ``None``, numeric zero of all types, and empty\nstrings and containers (including strings, tuples, lists,\ndictionaries, sets and frozensets). All other values are interpreted\nas true. User-defined objects can customize their truth value by\nproviding a ``__bool__()`` method.\n\nThe operator ``not`` yields ``True`` if its argument is false,\n``False`` otherwise.\n\nThe expression ``x and y`` first evaluates *x*; if *x* is false, its\nvalue is returned; otherwise, *y* is evaluated and the resulting value\nis returned.\n\nThe expression ``x or y`` first evaluates *x*; if *x* is true, its\nvalue is returned; otherwise, *y* is evaluated and the resulting value\nis returned.\n\n(Note that neither ``and`` nor ``or`` restrict the value and type they\nreturn to ``False`` and ``True``, but rather return the last evaluated\nargument. This is sometimes useful, e.g., if ``s`` is a string that\nshould be replaced by a default value if it is empty, the expression\n``s or \'foo\'`` yields the desired value. Because ``not`` has to\ninvent a value anyway, it does not bother to return a value of the\nsame type as its argument, so e.g., ``not \'foo\'`` yields ``False``,\nnot ``\'\'``.)\n', - 'break': '\nThe ``break`` statement\n***********************\n\n break_stmt ::= "break"\n\n``break`` may only occur syntactically nested in a ``for`` or\n``while`` loop, but not nested in a function or class definition\nwithin that loop.\n\nIt terminates the nearest enclosing loop, skipping the optional\n``else`` clause if the loop has one.\n\nIf a ``for`` loop is terminated by ``break``, the loop control target\nkeeps its current value.\n\nWhen ``break`` passes control out of a ``try`` statement with a\n``finally`` clause, that ``finally`` clause is executed before really\nleaving the loop.\n', - 'callable-types': '\nEmulating callable objects\n**************************\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, ``x(arg1, arg2, ...)`` is a shorthand for\n ``x.__call__(arg1, arg2, ...)``.\n', - 'calls': '\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","] | comprehension] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," keyword_arguments] ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nA trailing comma may be present after the positional and keyword\narguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and all objects having a\n``__call__()`` method are callable). All argument expressions are\nevaluated before the call is attempted. Please refer to section\n*Function definitions* for the syntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a ``TypeError`` exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is ``None``, it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a\n``TypeError`` exception is raised. Otherwise, the list of filled\nslots is used as the argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use ``PyArg_ParseTuple()`` to\nparse their arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a ``TypeError`` exception is raised, unless a formal parameter\nusing the syntax ``*identifier`` is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a ``TypeError`` exception is raised, unless a formal parameter\nusing the syntax ``**identifier`` is present; in this case, that\nformal parameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax ``*expression`` appears in the function call,\n``expression`` must evaluate to an iterable. Elements from this\niterable are treated as if they were additional positional arguments;\nif there are positional arguments *x1*, ..., *xN*, and ``expression``\nevaluates to a sequence *y1*, ..., *yM*, this is equivalent to a call\nwith M+N positional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the ``*expression`` syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the ``**expression`` argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print(a, b)\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the ``*expression``\nsyntax to be used in the same call, so in practice this confusion does\nnot arise.\n\nIf the syntax ``**expression`` appears in the function call,\n``expression`` must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both ``expression`` and as an explicit keyword argument,\na ``TypeError`` exception is raised.\n\nFormal parameters using the syntax ``*identifier`` or ``**identifier``\ncannot be used as positional argument slots or as keyword argument\nnames.\n\nA call always returns some value, possibly ``None``, unless it raises\nan exception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a ``return``\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a ``__call__()`` method; the effect is then\n the same as if that method was called.\n', - 'class': '\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class ``object``; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with ``self.name = value``. Both class and\ninstance attributes are accessible through the notation\n"``self.name``", and an instance attribute hides a class attribute\nwith the same name when accessed in this way. Class attributes can be\nused as defaults for instance attributes, but using mutable values\nthere can lead to unexpected results. *Descriptors* can be used to\ncreate instance variables with different implementation details.\n\nSee also:\n\n **PEP 3115** - Metaclasses in Python 3 **PEP 3129** - Class\n Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless there\n is a ``finally`` clause which happens to raise another exception.\n That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of an\n exception or the execution of a ``return``, ``continue``, or\n ``break`` statement.\n\n[3] A string literal appearing as the first statement in the function\n body is transformed into the function\'s ``__doc__`` attribute and\n therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s ``__doc__`` item and\n therefore the class\'s *docstring*.\n', - 'comparisons': '\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like ``a < b < c`` have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: ``True`` or ``False``.\n\nComparisons can be chained arbitrarily, e.g., ``x < y <= z`` is\nequivalent to ``x < y and y <= z``, except that ``y`` is evaluated\nonly once (but in both cases ``z`` is not evaluated at all when ``x <\ny`` is found to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then ``a op1 b op2 c ... y\nopN z`` is equivalent to ``a op1 b and b op2 c and ... y opN z``,\nexcept that each expression is evaluated at most once.\n\nNote that ``a op1 b op2 c`` doesn\'t imply any kind of comparison\nbetween *a* and *c*, so that, e.g., ``x < y > z`` is perfectly legal\n(though perhaps not pretty).\n\nThe operators ``<``, ``>``, ``==``, ``>=``, ``<=``, and ``!=`` compare\nthe values of two objects. The objects need not have the same type.\nIf both are numbers, they are converted to a common type. Otherwise,\nthe ``==`` and ``!=`` operators *always* consider objects of different\ntypes to be unequal, while the ``<``, ``>``, ``>=`` and ``<=``\noperators raise a ``TypeError`` when comparing objects of different\ntypes that do not implement these operators for the given pair of\ntypes. You can control comparison behavior of objects of non-built-in\ntypes by defining rich comparison methods like ``__gt__()``, described\nin section *Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values ``float(\'NaN\')`` and ``Decimal(\'NaN\')`` are special. The\n are identical to themselves, ``x is x`` but are not equal to\n themselves, ``x != x``. Additionally, comparing any value to a\n not-a-number value will return ``False``. For example, both ``3 <\n float(\'NaN\')`` and ``float(\'NaN\') < 3`` will return ``False``.\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric equivalents\n (the result of the built-in function ``ord()``) of their characters.\n [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison of\n corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, ``[1,2,x] <= [1,2,y]`` has the\n same value as ``x <= y``. If the corresponding element does not\n exist, the shorter sequence is ordered first (for example, ``[1,2] <\n [1,2,3]``).\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same ``(key, value)`` pairs. Order comparisons ``(\'<\', \'<=\', \'>=\',\n \'>\')`` raise ``TypeError``.\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets ``{1,2}`` and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, ``min()``, ``max()``, and ``sorted()`` produce\n undefined results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they are\n the same object; the choice whether one object is considered smaller\n or larger than another one is made arbitrarily but consistently\n within one execution of a program.\n\nComparison of objects of the differing types depends on whether either\nof the types provide explicit support for the comparison. Most\nnumeric types can be compared with one another. When cross-type\ncomparison is not supported, the comparison method returns\n``NotImplemented``.\n\nThe operators ``in`` and ``not in`` test for membership. ``x in s``\nevaluates to true if *x* is a member of *s*, and false otherwise. ``x\nnot in s`` returns the negation of ``x in s``. All built-in sequences\nand set types support this as well as dictionary, for which ``in``\ntests whether a the dictionary has a given key. For container types\nsuch as list, tuple, set, frozenset, dict, or collections.deque, the\nexpression ``x in y`` is equivalent to ``any(x is e or x == e for e in\ny)``.\n\nFor the string and bytes types, ``x in y`` is true if and only if *x*\nis a substring of *y*. An equivalent test is ``y.find(x) != -1``.\nEmpty strings are always considered to be a substring of any other\nstring, so ``"" in "abc"`` will return ``True``.\n\nFor user-defined classes which define the ``__contains__()`` method,\n``x in y`` is true if and only if ``y.__contains__(x)`` is true.\n\nFor user-defined classes which do not define ``__contains__()`` but do\ndefine ``__iter__()``, ``x in y`` is true if some value ``z`` with ``x\n== z`` is produced while iterating over ``y``. If an exception is\nraised during the iteration, it is as if ``in`` raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n``__getitem__()``, ``x in y`` is true if and only if there is a non-\nnegative integer index *i* such that ``x == y[i]``, and all lower\ninteger indices do not raise ``IndexError`` exception. (If any other\nexception is raised, it is as if ``in`` raised that exception).\n\nThe operator ``not in`` is defined to have the inverse true value of\n``in``.\n\nThe operators ``is`` and ``is not`` test for object identity: ``x is\ny`` is true if and only if *x* and *y* are the same object. ``x is\nnot y`` yields the inverse truth value. [4]\n', - 'compound': '\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe ``if``, ``while`` and ``for`` statements implement traditional\ncontrol flow constructs. ``try`` specifies exception handlers and/or\ncleanup code for a group of statements, while the ``with`` statement\nallows the execution of initialization and finalization code around a\nblock of code. Function and class definitions are also syntactically\ncompound statements.\n\nCompound statements consist of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which ``if`` clause a following ``else`` clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n``print()`` calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a ``NEWLINE`` possibly followed by\na ``DEDENT``. Also note that optional continuation clauses always\nbegin with a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling ``else``\' problem is solved in Python by\nrequiring nested ``if`` statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe ``if`` statement\n====================\n\nThe ``if`` statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the ``if`` statement is executed or evaluated).\nIf all expressions are false, the suite of the ``else`` clause, if\npresent, is executed.\n\n\nThe ``while`` statement\n=======================\n\nThe ``while`` statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the ``else`` clause, if present, is\nexecuted and the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ngoes back to testing the expression.\n\n\nThe ``for`` statement\n=====================\n\nThe ``for`` statement is used to iterate over the elements of a\nsequence (such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n``expression_list``. The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a ``StopIteration``\nexception), the suite in the ``else`` clause, if present, is executed,\nand the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ncontinues with the next item, or with the ``else`` clause if there was\nno next item.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function ``range()`` returns an\niterator of integers suitable to emulate the effect of Pascal\'s ``for\ni := a to b do``; e.g., ``list(range(3))`` returns the list ``[0, 1,\n2]``.\n\nNote: There is a subtlety when the sequence is being modified by the loop\n (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe ``try`` statement\n=====================\n\nThe ``try`` statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" target]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe ``except`` clause(s) specify one or more exception handlers. When\nno exception occurs in the ``try`` clause, no exception handler is\nexecuted. When an exception occurs in the ``try`` suite, a search for\nan exception handler is started. This search inspects the except\nclauses in turn until one is found that matches the exception. An\nexpression-less except clause, if present, must be last; it matches\nany exception. For an except clause with an expression, that\nexpression is evaluated, and the clause matches the exception if the\nresulting object is "compatible" with the exception. An object is\ncompatible with an exception if it is the class or a base class of the\nexception object or a tuple containing an item compatible with the\nexception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire ``try`` statement\nraised the exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the ``as`` keyword in that except clause,\nif present, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using ``as target``, it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the ``sys`` module and can be access via\n``sys.exc_info()``. ``sys.exc_info()`` returns a 3-tuple consisting of\nthe exception class, the exception instance and a traceback object\n(see section *The standard type hierarchy*) identifying the point in\nthe program where the exception occurred. ``sys.exc_info()`` values\nare restored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional ``else`` clause is executed if and when control flows off\nthe end of the ``try`` clause. [2] Exceptions in the ``else`` clause\nare not handled by the preceding ``except`` clauses.\n\nIf ``finally`` is present, it specifies a \'cleanup\' handler. The\n``try`` clause is executed, including any ``except`` and ``else``\nclauses. If an exception occurs in any of the clauses and is not\nhandled, the exception is temporarily saved. The ``finally`` clause is\nexecuted. If there is a saved exception it is re-raised at the end of\nthe ``finally`` clause. If the ``finally`` clause raises another\nexception, the saved exception is set as the context of the new\nexception. If the ``finally`` clause executes a ``return`` or\n``break`` statement, the saved exception is discarded:\n\n def f():\n try:\n 1/0\n finally:\n return 42\n\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the ``finally`` clause.\n\nWhen a ``return``, ``break`` or ``continue`` statement is executed in\nthe ``try`` suite of a ``try``...``finally`` statement, the\n``finally`` clause is also executed \'on the way out.\' A ``continue``\nstatement is illegal in the ``finally`` clause. (The reason is a\nproblem with the current implementation --- this restriction may be\nlifted in the future).\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the ``raise`` statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe ``with`` statement\n======================\n\nThe ``with`` statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common\n``try``...``except``...``finally`` usage patterns to be encapsulated\nfor convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the ``with`` statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the ``with_item``)\n is evaluated to obtain a context manager.\n\n2. The context manager\'s ``__exit__()`` is loaded for later use.\n\n3. The context manager\'s ``__enter__()`` method is invoked.\n\n4. If a target was included in the ``with`` statement, the return\n value from ``__enter__()`` is assigned to it.\n\n Note: The ``with`` statement guarantees that if the ``__enter__()``\n method returns without an error, then ``__exit__()`` will always\n be called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s ``__exit__()`` method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to ``__exit__()``. Otherwise,\n three ``None`` arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the ``__exit__()`` method was false, the exception is\n reraised. If the return value was true, the exception is\n suppressed, and execution continues with the statement following\n the ``with`` statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from ``__exit__()`` is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple ``with`` statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* ``=``\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the "``*``" must also have a default value ---\nthis is a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use ``None`` as the\ndefault, and explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n"``*identifier``" is present, it is initialized to a tuple receiving\nany excess positional parameters, defaulting to the empty tuple. If\nthe form "``**identifier``" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after "``*``" or "``*identifier``" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "``: expression``"\nfollowing the parameter name. Any parameter may have an annotation\neven those of the form ``*identifier`` or ``**identifier``. Functions\nmay have "return" annotation of the form "``-> expression``" after the\nparameter list. These annotations can be any valid Python expression\nand are evaluated when the function definition is executed.\nAnnotations may be evaluated in a different order than they appear in\nthe source code. The presence of annotations does not change the\nsemantics of a function. The annotation values are available as\nvalues of a dictionary keyed by the parameters\' names in the\n``__annotations__`` attribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a "``def``" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The "``def``" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A "``def``"\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also:\n\n **PEP 3107** - Function Annotations\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class ``object``; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with ``self.name = value``. Both class and\ninstance attributes are accessible through the notation\n"``self.name``", and an instance attribute hides a class attribute\nwith the same name when accessed in this way. Class attributes can be\nused as defaults for instance attributes, but using mutable values\nthere can lead to unexpected results. *Descriptors* can be used to\ncreate instance variables with different implementation details.\n\nSee also:\n\n **PEP 3115** - Metaclasses in Python 3 **PEP 3129** - Class\n Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless there\n is a ``finally`` clause which happens to raise another exception.\n That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of an\n exception or the execution of a ``return``, ``continue``, or\n ``break`` statement.\n\n[3] A string literal appearing as the first statement in the function\n body is transformed into the function\'s ``__doc__`` attribute and\n therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s ``__doc__`` item and\n therefore the class\'s *docstring*.\n', - 'context-managers': '\nWith Statement Context Managers\n*******************************\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a ``with`` statement. The context\nmanager handles the entry into, and the exit from, the desired runtime\ncontext for the execution of the block of code. Context managers are\nnormally invoked using the ``with`` statement (described in section\n*The with statement*), but can also be used by directly invoking their\nmethods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The ``with``\n statement will bind this method\'s return value to the target(s)\n specified in the ``as`` clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be ``None``.\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that ``__exit__()`` methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` statement.\n', - 'continue': '\nThe ``continue`` statement\n**************************\n\n continue_stmt ::= "continue"\n\n``continue`` may only occur syntactically nested in a ``for`` or\n``while`` loop, but not nested in a function or class definition or\n``finally`` clause within that loop. It continues with the next cycle\nof the nearest enclosing loop.\n\nWhen ``continue`` passes control out of a ``try`` statement with a\n``finally`` clause, that ``finally`` clause is executed before really\nstarting the next loop cycle.\n', - 'conversions': '\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," this means\nthat the operator implementation for built-in types works that way:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the other\n is converted to floating point;\n\n* otherwise, both must be integers and no conversion is necessary.\n\nSome additional rules apply for certain operators (e.g., a string left\nargument to the \'%\' operator). Extensions must define their own\nconversion behavior.\n', - 'customization': '\nBasic customization\n*******************\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. ``__new__()`` is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of ``__new__()`` should be the new object instance (usually\n an instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s ``__new__()`` method using\n ``super(currentclass, cls).__new__(cls[, ...])`` with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If ``__new__()`` returns an instance of *cls*, then the new\n instance\'s ``__init__()`` method will be invoked like\n ``__init__(self[, ...])``, where *self* is the new instance and the\n remaining arguments are the same as were passed to ``__new__()``.\n\n If ``__new__()`` does not return an instance of *cls*, then the new\n instance\'s ``__init__()`` method will not be invoked.\n\n ``__new__()`` is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called when the instance is created. The arguments are those\n passed to the class constructor expression. If a base class has an\n ``__init__()`` method, the derived class\'s ``__init__()`` method,\n if any, must explicitly call it to ensure proper initialization of\n the base class part of the instance; for example:\n ``BaseClass.__init__(self, [args...])``. As a special constraint\n on constructors, no value may be returned; doing so will cause a\n ``TypeError`` to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a ``__del__()`` method,\n the derived class\'s ``__del__()`` method, if any, must explicitly\n call it to ensure proper deletion of the base class part of the\n instance. Note that it is possible (though not recommended!) for\n the ``__del__()`` method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n ``__del__()`` methods are called for objects that still exist when\n the interpreter exits.\n\n Note: ``del x`` doesn\'t directly call ``x.__del__()`` --- the former\n decrements the reference count for ``x`` by one, and the latter\n is only called when ``x``\'s reference count reaches zero. Some\n common situations that may prevent the reference count of an\n object from going to zero include: circular references between\n objects (e.g., a doubly-linked list or a tree data structure with\n parent and child pointers); a reference to the object on the\n stack frame of a function that caught an exception (the traceback\n stored in ``sys.exc_info()[2]`` keeps the stack frame alive); or\n a reference to the object on the stack frame that raised an\n unhandled exception in interactive mode (the traceback stored in\n ``sys.last_traceback`` keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing ``None`` in\n ``sys.last_traceback``. Circular references which are garbage are\n detected when the option cycle detector is enabled (it\'s on by\n default), but can only be cleaned up if there are no Python-\n level ``__del__()`` methods involved. Refer to the documentation\n for the ``gc`` module for more information about how\n ``__del__()`` methods are handled by the cycle detector,\n particularly the description of the ``garbage`` value.\n\n Warning: Due to the precarious circumstances under which ``__del__()``\n methods are invoked, exceptions that occur during their execution\n are ignored, and a warning is printed to ``sys.stderr`` instead.\n Also, when ``__del__()`` is invoked in response to a module being\n deleted (e.g., when execution of the program is done), other\n globals referenced by the ``__del__()`` method may already have\n been deleted or in the process of being torn down (e.g. the\n import machinery shutting down). For this reason, ``__del__()``\n methods should do the absolute minimum needed to maintain\n external invariants. Starting with version 1.5, Python\n guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the ``__del__()`` method is called.\n\nobject.__repr__(self)\n\n Called by the ``repr()`` built-in function to compute the\n "official" string representation of an object. If at all possible,\n this should look like a valid Python expression that could be used\n to recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n ``<...some useful description...>`` should be returned. The return\n value must be a string object. If a class defines ``__repr__()``\n but not ``__str__()``, then ``__repr__()`` is also used when an\n "informal" string representation of instances of that class is\n required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by ``str(object)`` and the built-in functions ``format()``\n and ``print()`` to compute the "informal" or nicely printable\n string representation of an object. The return value must be a\n *string* object.\n\n This method differs from ``object.__repr__()`` in that there is no\n expectation that ``__str__()`` return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type ``object``\n calls ``object.__repr__()``.\n\nobject.__bytes__(self)\n\n Called by ``bytes()`` to compute a byte-string representation of an\n object. This should return a ``bytes`` object.\n\nobject.__format__(self, format_spec)\n\n Called by the ``format()`` built-in function (and by extension, the\n ``str.format()`` method of class ``str``) to produce a "formatted"\n string representation of an object. The ``format_spec`` argument is\n a string that contains a description of the formatting options\n desired. The interpretation of the ``format_spec`` argument is up\n to the type implementing ``__format__()``, however most classes\n will either delegate formatting to one of the built-in types, or\n use a similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: ``xy`` calls ``x.__gt__(y)``, and ``x>=y`` calls\n ``x.__ge__(y)``.\n\n A rich comparison method may return the singleton\n ``NotImplemented`` if it does not implement the operation for a\n given pair of arguments. By convention, ``False`` and ``True`` are\n returned for a successful comparison. However, these methods can\n return any value, so if the comparison operator is used in a\n Boolean context (e.g., in the condition of an ``if`` statement),\n Python will call ``bool()`` on the value to determine if the result\n is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of ``x==y`` does not imply that ``x!=y`` is false.\n Accordingly, when defining ``__eq__()``, one should also define\n ``__ne__()`` so that the operators will behave as expected. See\n the paragraph on ``__hash__()`` for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, ``__lt__()`` and ``__gt__()`` are each\n other\'s reflection, ``__le__()`` and ``__ge__()`` are each other\'s\n reflection, and ``__eq__()`` and ``__ne__()`` are their own\n reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see ``functools.total_ordering()``.\n\nobject.__hash__(self)\n\n Called by built-in function ``hash()`` and for operations on\n members of hashed collections including ``set``, ``frozenset``, and\n ``dict``. ``__hash__()`` should return an integer. The only\n required property is that objects which compare equal have the same\n hash value; it is advised to somehow mix together (e.g. using\n exclusive or) the hash values for the components of the object that\n also play a part in comparison of objects.\n\n Note: ``hash()`` truncates the value returned from an object\'s custom\n ``__hash__()`` method to the size of a ``Py_ssize_t``. This is\n typically 8 bytes on 64-bit builds and 4 bytes on 32-bit builds.\n If an object\'s ``__hash__()`` must interoperate on builds of\n different bit sizes, be sure to check the width on all supported\n builds. An easy way to do this is with ``python -c "import sys;\n print(sys.hash_info.width)"``\n\n If a class does not define an ``__eq__()`` method it should not\n define a ``__hash__()`` operation either; if it defines\n ``__eq__()`` but not ``__hash__()``, its instances will not be\n usable as items in hashable collections. If a class defines\n mutable objects and implements an ``__eq__()`` method, it should\n not implement ``__hash__()``, since the implementation of hashable\n collections requires that a key\'s hash value is immutable (if the\n object\'s hash value changes, it will be in the wrong hash bucket).\n\n User-defined classes have ``__eq__()`` and ``__hash__()`` methods\n by default; with them, all objects compare unequal (except with\n themselves) and ``x.__hash__()`` returns an appropriate value such\n that ``x == y`` implies both that ``x is y`` and ``hash(x) ==\n hash(y)``.\n\n A class that overrides ``__eq__()`` and does not define\n ``__hash__()`` will have its ``__hash__()`` implicitly set to\n ``None``. When the ``__hash__()`` method of a class is ``None``,\n instances of the class will raise an appropriate ``TypeError`` when\n a program attempts to retrieve their hash value, and will also be\n correctly identified as unhashable when checking ``isinstance(obj,\n collections.Hashable``).\n\n If a class that overrides ``__eq__()`` needs to retain the\n implementation of ``__hash__()`` from a parent class, the\n interpreter must be told this explicitly by setting ``__hash__ =\n .__hash__``.\n\n If a class that does not override ``__eq__()`` wishes to suppress\n hash support, it should include ``__hash__ = None`` in the class\n definition. A class which defines its own ``__hash__()`` that\n explicitly raises a ``TypeError`` would be incorrectly identified\n as hashable by an ``isinstance(obj, collections.Hashable)`` call.\n\n Note: By default, the ``__hash__()`` values of str, bytes and datetime\n objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also ``PYTHONHASHSEED``.\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n ``bool()``; should return ``False`` or ``True``. When this method\n is not defined, ``__len__()`` is called, if it is defined, and the\n object is considered true if its result is nonzero. If a class\n defines neither ``__len__()`` nor ``__bool__()``, all its instances\n are considered true.\n', - 'debugger': '\n``pdb`` --- The Python Debugger\n*******************************\n\nThe module ``pdb`` defines an interactive source code debugger for\nPython programs. It supports setting (conditional) breakpoints and\nsingle stepping at the source line level, inspection of stack frames,\nsource code listing, and evaluation of arbitrary Python code in the\ncontext of any stack frame. It also supports post-mortem debugging\nand can be called under program control.\n\nThe debugger is extensible -- it is actually defined as the class\n``Pdb``. This is currently undocumented but easily understood by\nreading the source. The extension interface uses the modules ``bdb``\nand ``cmd``.\n\nThe debugger\'s prompt is ``(Pdb)``. Typical usage to run a program\nunder control of the debugger is:\n\n >>> import pdb\n >>> import mymodule\n >>> pdb.run(\'mymodule.test()\')\n > (0)?()\n (Pdb) continue\n > (1)?()\n (Pdb) continue\n NameError: \'spam\'\n > (1)?()\n (Pdb)\n\nChanged in version 3.3: Tab-completion via the ``readline`` module is\navailable for commands and command arguments, e.g. the current global\nand local names are offered as arguments of the ``print`` command.\n\n``pdb.py`` can also be invoked as a script to debug other scripts.\nFor example:\n\n python3 -m pdb myscript.py\n\nWhen invoked as a script, pdb will automatically enter post-mortem\ndebugging if the program being debugged exits abnormally. After post-\nmortem debugging (or after normal exit of the program), pdb will\nrestart the program. Automatic restarting preserves pdb\'s state (such\nas breakpoints) and in most cases is more useful than quitting the\ndebugger upon program\'s exit.\n\nNew in version 3.2: ``pdb.py`` now accepts a ``-c`` option that\nexecutes commands as if given in a ``.pdbrc`` file, see *Debugger\nCommands*.\n\nThe typical usage to break into the debugger from a running program is\nto insert\n\n import pdb; pdb.set_trace()\n\nat the location you want to break into the debugger. You can then\nstep through the code following this statement, and continue running\nwithout the debugger using the ``continue`` command.\n\nThe typical usage to inspect a crashed program is:\n\n >>> import pdb\n >>> import mymodule\n >>> mymodule.test()\n Traceback (most recent call last):\n File "", line 1, in ?\n File "./mymodule.py", line 4, in test\n test2()\n File "./mymodule.py", line 3, in test2\n print(spam)\n NameError: spam\n >>> pdb.pm()\n > ./mymodule.py(3)test2()\n -> print(spam)\n (Pdb)\n\nThe module defines the following functions; each enters the debugger\nin a slightly different way:\n\npdb.run(statement, globals=None, locals=None)\n\n Execute the *statement* (given as a string or a code object) under\n debugger control. The debugger prompt appears before any code is\n executed; you can set breakpoints and type ``continue``, or you can\n step through the statement using ``step`` or ``next`` (all these\n commands are explained below). The optional *globals* and *locals*\n arguments specify the environment in which the code is executed; by\n default the dictionary of the module ``__main__`` is used. (See\n the explanation of the built-in ``exec()`` or ``eval()``\n functions.)\n\npdb.runeval(expression, globals=None, locals=None)\n\n Evaluate the *expression* (given as a string or a code object)\n under debugger control. When ``runeval()`` returns, it returns the\n value of the expression. Otherwise this function is similar to\n ``run()``.\n\npdb.runcall(function, *args, **kwds)\n\n Call the *function* (a function or method object, not a string)\n with the given arguments. When ``runcall()`` returns, it returns\n whatever the function call returned. The debugger prompt appears\n as soon as the function is entered.\n\npdb.set_trace()\n\n Enter the debugger at the calling stack frame. This is useful to\n hard-code a breakpoint at a given point in a program, even if the\n code is not otherwise being debugged (e.g. when an assertion\n fails).\n\npdb.post_mortem(traceback=None)\n\n Enter post-mortem debugging of the given *traceback* object. If no\n *traceback* is given, it uses the one of the exception that is\n currently being handled (an exception must be being handled if the\n default is to be used).\n\npdb.pm()\n\n Enter post-mortem debugging of the traceback found in\n ``sys.last_traceback``.\n\nThe ``run*`` functions and ``set_trace()`` are aliases for\ninstantiating the ``Pdb`` class and calling the method of the same\nname. If you want to access further features, you have to do this\nyourself:\n\nclass class pdb.Pdb(completekey=\'tab\', stdin=None, stdout=None, skip=None, nosigint=False)\n\n ``Pdb`` is the debugger class.\n\n The *completekey*, *stdin* and *stdout* arguments are passed to the\n underlying ``cmd.Cmd`` class; see the description there.\n\n The *skip* argument, if given, must be an iterable of glob-style\n module name patterns. The debugger will not step into frames that\n originate in a module that matches one of these patterns. [1]\n\n By default, Pdb sets a handler for the SIGINT signal (which is sent\n when the user presses Ctrl-C on the console) when you give a\n ``continue`` command. This allows you to break into the debugger\n again by pressing Ctrl-C. If you want Pdb not to touch the SIGINT\n handler, set *nosigint* tot true.\n\n Example call to enable tracing with *skip*:\n\n import pdb; pdb.Pdb(skip=[\'django.*\']).set_trace()\n\n New in version 3.1: The *skip* argument.\n\n New in version 3.2: The *nosigint* argument. Previously, a SIGINT\n handler was never set by Pdb.\n\n run(statement, globals=None, locals=None)\n runeval(expression, globals=None, locals=None)\n runcall(function, *args, **kwds)\n set_trace()\n\n See the documentation for the functions explained above.\n\n\nDebugger Commands\n=================\n\nThe commands recognized by the debugger are listed below. Most\ncommands can be abbreviated to one or two letters as indicated; e.g.\n``h(elp)`` means that either ``h`` or ``help`` can be used to enter\nthe help command (but not ``he`` or ``hel``, nor ``H`` or ``Help`` or\n``HELP``). Arguments to commands must be separated by whitespace\n(spaces or tabs). Optional arguments are enclosed in square brackets\n(``[]``) in the command syntax; the square brackets must not be typed.\nAlternatives in the command syntax are separated by a vertical bar\n(``|``).\n\nEntering a blank line repeats the last command entered. Exception: if\nthe last command was a ``list`` command, the next 11 lines are listed.\n\nCommands that the debugger doesn\'t recognize are assumed to be Python\nstatements and are executed in the context of the program being\ndebugged. Python statements can also be prefixed with an exclamation\npoint (``!``). This is a powerful way to inspect the program being\ndebugged; it is even possible to change a variable or call a function.\nWhen an exception occurs in such a statement, the exception name is\nprinted but the debugger\'s state is not changed.\n\nThe debugger supports *aliases*. Aliases can have parameters which\nallows one a certain level of adaptability to the context under\nexamination.\n\nMultiple commands may be entered on a single line, separated by\n``;;``. (A single ``;`` is not used as it is the separator for\nmultiple commands in a line that is passed to the Python parser.) No\nintelligence is applied to separating the commands; the input is split\nat the first ``;;`` pair, even if it is in the middle of a quoted\nstring.\n\nIf a file ``.pdbrc`` exists in the user\'s home directory or in the\ncurrent directory, it is read in and executed as if it had been typed\nat the debugger prompt. This is particularly useful for aliases. If\nboth files exist, the one in the home directory is read first and\naliases defined there can be overridden by the local file.\n\nChanged in version 3.2: ``.pdbrc`` can now contain commands that\ncontinue debugging, such as ``continue`` or ``next``. Previously,\nthese commands had no effect.\n\nh(elp) [command]\n\n Without argument, print the list of available commands. With a\n *command* as argument, print help about that command. ``help pdb``\n displays the full documentation (the docstring of the ``pdb``\n module). Since the *command* argument must be an identifier,\n ``help exec`` must be entered to get help on the ``!`` command.\n\nw(here)\n\n Print a stack trace, with the most recent frame at the bottom. An\n arrow indicates the current frame, which determines the context of\n most commands.\n\nd(own) [count]\n\n Move the current frame *count* (default one) levels down in the\n stack trace (to a newer frame).\n\nu(p) [count]\n\n Move the current frame *count* (default one) levels up in the stack\n trace (to an older frame).\n\nb(reak) [([filename:]lineno | function) [, condition]]\n\n With a *lineno* argument, set a break there in the current file.\n With a *function* argument, set a break at the first executable\n statement within that function. The line number may be prefixed\n with a filename and a colon, to specify a breakpoint in another\n file (probably one that hasn\'t been loaded yet). The file is\n searched on ``sys.path``. Note that each breakpoint is assigned a\n number to which all the other breakpoint commands refer.\n\n If a second argument is present, it is an expression which must\n evaluate to true before the breakpoint is honored.\n\n Without argument, list all breaks, including for each breakpoint,\n the number of times that breakpoint has been hit, the current\n ignore count, and the associated condition if any.\n\ntbreak [([filename:]lineno | function) [, condition]]\n\n Temporary breakpoint, which is removed automatically when it is\n first hit. The arguments are the same as for ``break``.\n\ncl(ear) [filename:lineno | bpnumber [bpnumber ...]]\n\n With a *filename:lineno* argument, clear all the breakpoints at\n this line. With a space separated list of breakpoint numbers, clear\n those breakpoints. Without argument, clear all breaks (but first\n ask confirmation).\n\ndisable [bpnumber [bpnumber ...]]\n\n Disable the breakpoints given as a space separated list of\n breakpoint numbers. Disabling a breakpoint means it cannot cause\n the program to stop execution, but unlike clearing a breakpoint, it\n remains in the list of breakpoints and can be (re-)enabled.\n\nenable [bpnumber [bpnumber ...]]\n\n Enable the breakpoints specified.\n\nignore bpnumber [count]\n\n Set the ignore count for the given breakpoint number. If count is\n omitted, the ignore count is set to 0. A breakpoint becomes active\n when the ignore count is zero. When non-zero, the count is\n decremented each time the breakpoint is reached and the breakpoint\n is not disabled and any associated condition evaluates to true.\n\ncondition bpnumber [condition]\n\n Set a new *condition* for the breakpoint, an expression which must\n evaluate to true before the breakpoint is honored. If *condition*\n is absent, any existing condition is removed; i.e., the breakpoint\n is made unconditional.\n\ncommands [bpnumber]\n\n Specify a list of commands for breakpoint number *bpnumber*. The\n commands themselves appear on the following lines. Type a line\n containing just ``end`` to terminate the commands. An example:\n\n (Pdb) commands 1\n (com) print some_variable\n (com) end\n (Pdb)\n\n To remove all commands from a breakpoint, type commands and follow\n it immediately with ``end``; that is, give no commands.\n\n With no *bpnumber* argument, commands refers to the last breakpoint\n set.\n\n You can use breakpoint commands to start your program up again.\n Simply use the continue command, or step, or any other command that\n resumes execution.\n\n Specifying any command resuming execution (currently continue,\n step, next, return, jump, quit and their abbreviations) terminates\n the command list (as if that command was immediately followed by\n end). This is because any time you resume execution (even with a\n simple next or step), you may encounter another breakpoint--which\n could have its own command list, leading to ambiguities about which\n list to execute.\n\n If you use the \'silent\' command in the command list, the usual\n message about stopping at a breakpoint is not printed. This may be\n desirable for breakpoints that are to print a specific message and\n then continue. If none of the other commands print anything, you\n see no sign that the breakpoint was reached.\n\ns(tep)\n\n Execute the current line, stop at the first possible occasion\n (either in a function that is called or on the next line in the\n current function).\n\nn(ext)\n\n Continue execution until the next line in the current function is\n reached or it returns. (The difference between ``next`` and\n ``step`` is that ``step`` stops inside a called function, while\n ``next`` executes called functions at (nearly) full speed, only\n stopping at the next line in the current function.)\n\nunt(il) [lineno]\n\n Without argument, continue execution until the line with a number\n greater than the current one is reached.\n\n With a line number, continue execution until a line with a number\n greater or equal to that is reached. In both cases, also stop when\n the current frame returns.\n\n Changed in version 3.2: Allow giving an explicit line number.\n\nr(eturn)\n\n Continue execution until the current function returns.\n\nc(ont(inue))\n\n Continue execution, only stop when a breakpoint is encountered.\n\nj(ump) lineno\n\n Set the next line that will be executed. Only available in the\n bottom-most frame. This lets you jump back and execute code again,\n or jump forward to skip code that you don\'t want to run.\n\n It should be noted that not all jumps are allowed -- for instance\n it is not possible to jump into the middle of a ``for`` loop or out\n of a ``finally`` clause.\n\nl(ist) [first[, last]]\n\n List source code for the current file. Without arguments, list 11\n lines around the current line or continue the previous listing.\n With ``.`` as argument, list 11 lines around the current line.\n With one argument, list 11 lines around at that line. With two\n arguments, list the given range; if the second argument is less\n than the first, it is interpreted as a count.\n\n The current line in the current frame is indicated by ``->``. If\n an exception is being debugged, the line where the exception was\n originally raised or propagated is indicated by ``>>``, if it\n differs from the current line.\n\n New in version 3.2: The ``>>`` marker.\n\nll | longlist\n\n List all source code for the current function or frame.\n Interesting lines are marked as for ``list``.\n\n New in version 3.2.\n\na(rgs)\n\n Print the argument list of the current function.\n\np(rint) expression\n\n Evaluate the *expression* in the current context and print its\n value.\n\npp expression\n\n Like the ``print`` command, except the value of the expression is\n pretty-printed using the ``pprint`` module.\n\nwhatis expression\n\n Print the type of the *expression*.\n\nsource expression\n\n Try to get source code for the given object and display it.\n\n New in version 3.2.\n\ndisplay [expression]\n\n Display the value of the expression if it changed, each time\n execution stops in the current frame.\n\n Without expression, list all display expressions for the current\n frame.\n\n New in version 3.2.\n\nundisplay [expression]\n\n Do not display the expression any more in the current frame.\n Without expression, clear all display expressions for the current\n frame.\n\n New in version 3.2.\n\ninteract\n\n Start an interative interpreter (using the ``code`` module) whose\n global namespace contains all the (global and local) names found in\n the current scope.\n\n New in version 3.2.\n\nalias [name [command]]\n\n Create an alias called *name* that executes *command*. The command\n must *not* be enclosed in quotes. Replaceable parameters can be\n indicated by ``%1``, ``%2``, and so on, while ``%*`` is replaced by\n all the parameters. If no command is given, the current alias for\n *name* is shown. If no arguments are given, all aliases are listed.\n\n Aliases may be nested and can contain anything that can be legally\n typed at the pdb prompt. Note that internal pdb commands *can* be\n overridden by aliases. Such a command is then hidden until the\n alias is removed. Aliasing is recursively applied to the first\n word of the command line; all other words in the line are left\n alone.\n\n As an example, here are two useful aliases (especially when placed\n in the ``.pdbrc`` file):\n\n # Print instance variables (usage "pi classInst")\n alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k])\n # Print instance variables in self\n alias ps pi self\n\nunalias name\n\n Delete the specified alias.\n\n! statement\n\n Execute the (one-line) *statement* in the context of the current\n stack frame. The exclamation point can be omitted unless the first\n word of the statement resembles a debugger command. To set a\n global variable, you can prefix the assignment command with a\n ``global`` statement on the same line, e.g.:\n\n (Pdb) global list_options; list_options = [\'-l\']\n (Pdb)\n\nrun [args ...]\nrestart [args ...]\n\n Restart the debugged Python program. If an argument is supplied,\n it is split with ``shlex`` and the result is used as the new\n ``sys.argv``. History, breakpoints, actions and debugger options\n are preserved. ``restart`` is an alias for ``run``.\n\nq(uit)\n\n Quit from the debugger. The program being executed is aborted.\n\n-[ Footnotes ]-\n\n[1] Whether a frame is considered to originate in a certain module is\n determined by the ``__name__`` in the frame globals.\n', - 'del': '\nThe ``del`` statement\n*********************\n\n del_stmt ::= "del" target_list\n\nDeletion is recursively defined very similar to the way assignment is\ndefined. Rather than spelling it out in full details, here are some\nhints.\n\nDeletion of a target list recursively deletes each target, from left\nto right.\n\nDeletion of a name removes the binding of that name from the local or\nglobal namespace, depending on whether the name occurs in a ``global``\nstatement in the same code block. If the name is unbound, a\n``NameError`` exception will be raised.\n\nDeletion of attribute references, subscriptions and slicings is passed\nto the primary object involved; deletion of a slicing is in general\nequivalent to assignment of an empty slice of the right type (but even\nthis is determined by the sliced object).\n\nChanged in version 3.2: Previously it was illegal to delete a name\nfrom the local namespace if it occurs as a free variable in a nested\nblock.\n', + 'attribute-access': '\nCustomizing attribute access\n****************************\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n========================\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n====================\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n=========\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n class, *__slots__* reserves space for the declared variables and\n prevents the automatic creation of *__dict__* and *__weakref__* for\n each instance.\n\n\nNotes on using *__slots__*\n--------------------------\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n', + 'attribute-references': '\nAttribute references\n********************\n\nAn attribute reference is a primary followed by a period and a name:\n\n attributeref ::= primary "." identifier\n\nThe primary must evaluate to an object of a type that supports\nattribute references, which most objects do. This object is then\nasked to produce the attribute whose name is the identifier (which can\nbe customized by overriding the "__getattr__()" method). If this\nattribute is not available, the exception "AttributeError" is raised.\nOtherwise, the type and value of the object produced is determined by\nthe object. Multiple evaluations of the same attribute reference may\nyield different objects.\n', + 'augassign': '\nAugmented assignment statements\n*******************************\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', + 'binary': '\nBinary arithmetic operations\n****************************\n\nThe binary arithmetic operations have the conventional priority\nlevels. Note that some of these operations also apply to certain non-\nnumeric types. Apart from the power operator, there are only two\nlevels, one for multiplicative operators and one for additive\noperators:\n\n m_expr ::= u_expr | m_expr "*" u_expr | m_expr "//" u_expr | m_expr "/" u_expr\n | m_expr "%" u_expr\n a_expr ::= m_expr | a_expr "+" m_expr | a_expr "-" m_expr\n\nThe "*" (multiplication) operator yields the product of its arguments.\nThe arguments must either both be numbers, or one argument must be an\ninteger and the other must be a sequence. In the former case, the\nnumbers are converted to a common type and then multiplied together.\nIn the latter case, sequence repetition is performed; a negative\nrepetition factor yields an empty sequence.\n\nThe "/" (division) and "//" (floor division) operators yield the\nquotient of their arguments. The numeric arguments are first\nconverted to a common type. Division of integers yields a float, while\nfloor division of integers results in an integer; the result is that\nof mathematical division with the \'floor\' function applied to the\nresult. Division by zero raises the "ZeroDivisionError" exception.\n\nThe "%" (modulo) operator yields the remainder from the division of\nthe first argument by the second. The numeric arguments are first\nconverted to a common type. A zero right argument raises the\n"ZeroDivisionError" exception. The arguments may be floating point\nnumbers, e.g., "3.14%0.7" equals "0.34" (since "3.14" equals "4*0.7 +\n0.34".) The modulo operator always yields a result with the same sign\nas its second operand (or zero); the absolute value of the result is\nstrictly smaller than the absolute value of the second operand [1].\n\nThe floor division and modulo operators are connected by the following\nidentity: "x == (x//y)*y + (x%y)". Floor division and modulo are also\nconnected with the built-in function "divmod()": "divmod(x, y) ==\n(x//y, x%y)". [2].\n\nIn addition to performing the modulo operation on numbers, the "%"\noperator is also overloaded by string objects to perform old-style\nstring formatting (also known as interpolation). The syntax for\nstring formatting is described in the Python Library Reference,\nsection *printf-style String Formatting*.\n\nThe floor division operator, the modulo operator, and the "divmod()"\nfunction are not defined for complex numbers. Instead, convert to a\nfloating point number using the "abs()" function if appropriate.\n\nThe "+" (addition) operator yields the sum of its arguments. The\narguments must either both be numbers or both sequences of the same\ntype. In the former case, the numbers are converted to a common type\nand then added together. In the latter case, the sequences are\nconcatenated.\n\nThe "-" (subtraction) operator yields the difference of its arguments.\nThe numeric arguments are first converted to a common type.\n', + 'bitwise': '\nBinary bitwise operations\n*************************\n\nEach of the three bitwise operations has a different priority level:\n\n and_expr ::= shift_expr | and_expr "&" shift_expr\n xor_expr ::= and_expr | xor_expr "^" and_expr\n or_expr ::= xor_expr | or_expr "|" xor_expr\n\nThe "&" operator yields the bitwise AND of its arguments, which must\nbe integers.\n\nThe "^" operator yields the bitwise XOR (exclusive OR) of its\narguments, which must be integers.\n\nThe "|" operator yields the bitwise (inclusive) OR of its arguments,\nwhich must be integers.\n', + 'bltin-code-objects': '\nCode Objects\n************\n\nCode objects are used by the implementation to represent "pseudo-\ncompiled" executable Python code such as a function body. They differ\nfrom function objects because they don\'t contain a reference to their\nglobal execution environment. Code objects are returned by the built-\nin "compile()" function and can be extracted from function objects\nthrough their "__code__" attribute. See also the "code" module.\n\nA code object can be executed or evaluated by passing it (instead of a\nsource string) to the "exec()" or "eval()" built-in functions.\n\nSee *The standard type hierarchy* for more information.\n', + 'bltin-ellipsis-object': '\nThe Ellipsis Object\n*******************\n\nThis object is commonly used by slicing (see *Slicings*). It supports\nno special operations. There is exactly one ellipsis object, named\n"Ellipsis" (a built-in name). "type(Ellipsis)()" produces the\n"Ellipsis" singleton.\n\nIt is written as "Ellipsis" or "...".\n', + 'bltin-null-object': '\nThe Null Object\n***************\n\nThis object is returned by functions that don\'t explicitly return a\nvalue. It supports no special operations. There is exactly one null\nobject, named "None" (a built-in name). "type(None)()" produces the\nsame singleton.\n\nIt is written as "None".\n', + 'bltin-type-objects': '\nType Objects\n************\n\nType objects represent the various object types. An object\'s type is\naccessed by the built-in function "type()". There are no special\noperations on types. The standard module "types" defines names for\nall standard built-in types.\n\nTypes are written like this: "".\n', + 'booleans': '\nBoolean operations\n******************\n\n or_test ::= and_test | or_test "or" and_test\n and_test ::= not_test | and_test "and" not_test\n not_test ::= comparison | "not" not_test\n\nIn the context of Boolean operations, and also when expressions are\nused by control flow statements, the following values are interpreted\nas false: "False", "None", numeric zero of all types, and empty\nstrings and containers (including strings, tuples, lists,\ndictionaries, sets and frozensets). All other values are interpreted\nas true. User-defined objects can customize their truth value by\nproviding a "__bool__()" method.\n\nThe operator "not" yields "True" if its argument is false, "False"\notherwise.\n\nThe expression "x and y" first evaluates *x*; if *x* is false, its\nvalue is returned; otherwise, *y* is evaluated and the resulting value\nis returned.\n\nThe expression "x or y" first evaluates *x*; if *x* is true, its value\nis returned; otherwise, *y* is evaluated and the resulting value is\nreturned.\n\n(Note that neither "and" nor "or" restrict the value and type they\nreturn to "False" and "True", but rather return the last evaluated\nargument. This is sometimes useful, e.g., if "s" is a string that\nshould be replaced by a default value if it is empty, the expression\n"s or \'foo\'" yields the desired value. Because "not" has to invent a\nvalue anyway, it does not bother to return a value of the same type as\nits argument, so e.g., "not \'foo\'" yields "False", not "\'\'".)\n', + 'break': '\nThe "break" statement\n*********************\n\n break_stmt ::= "break"\n\n"break" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition within that\nloop.\n\nIt terminates the nearest enclosing loop, skipping the optional "else"\nclause if the loop has one.\n\nIf a "for" loop is terminated by "break", the loop control target\nkeeps its current value.\n\nWhen "break" passes control out of a "try" statement with a "finally"\nclause, that "finally" clause is executed before really leaving the\nloop.\n', + 'callable-types': '\nEmulating callable objects\n**************************\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n', + 'calls': '\nCalls\n*****\n\nA call calls a callable object (e.g., a *function*) with a possibly\nempty series of *arguments*:\n\n call ::= primary "(" [argument_list [","] | comprehension] ")"\n argument_list ::= positional_arguments ["," keyword_arguments]\n ["," "*" expression] ["," keyword_arguments]\n ["," "**" expression]\n | keyword_arguments ["," "*" expression]\n ["," keyword_arguments] ["," "**" expression]\n | "*" expression ["," keyword_arguments] ["," "**" expression]\n | "**" expression\n positional_arguments ::= expression ("," expression)*\n keyword_arguments ::= keyword_item ("," keyword_item)*\n keyword_item ::= identifier "=" expression\n\nA trailing comma may be present after the positional and keyword\narguments but does not affect the semantics.\n\nThe primary must evaluate to a callable object (user-defined\nfunctions, built-in functions, methods of built-in objects, class\nobjects, methods of class instances, and all objects having a\n"__call__()" method are callable). All argument expressions are\nevaluated before the call is attempted. Please refer to section\n*Function definitions* for the syntax of formal *parameter* lists.\n\nIf keyword arguments are present, they are first converted to\npositional arguments, as follows. First, a list of unfilled slots is\ncreated for the formal parameters. If there are N positional\narguments, they are placed in the first N slots. Next, for each\nkeyword argument, the identifier is used to determine the\ncorresponding slot (if the identifier is the same as the first formal\nparameter name, the first slot is used, and so on). If the slot is\nalready filled, a "TypeError" exception is raised. Otherwise, the\nvalue of the argument is placed in the slot, filling it (even if the\nexpression is "None", it fills the slot). When all arguments have\nbeen processed, the slots that are still unfilled are filled with the\ncorresponding default value from the function definition. (Default\nvalues are calculated, once, when the function is defined; thus, a\nmutable object such as a list or dictionary used as default value will\nbe shared by all calls that don\'t specify an argument value for the\ncorresponding slot; this should usually be avoided.) If there are any\nunfilled slots for which no default value is specified, a "TypeError"\nexception is raised. Otherwise, the list of filled slots is used as\nthe argument list for the call.\n\n**CPython implementation detail:** An implementation may provide\nbuilt-in functions whose positional parameters do not have names, even\nif they are \'named\' for the purpose of documentation, and which\ntherefore cannot be supplied by keyword. In CPython, this is the case\nfor functions implemented in C that use "PyArg_ParseTuple()" to parse\ntheir arguments.\n\nIf there are more positional arguments than there are formal parameter\nslots, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "*identifier" is present; in this case, that formal\nparameter receives a tuple containing the excess positional arguments\n(or an empty tuple if there were no excess positional arguments).\n\nIf any keyword argument does not correspond to a formal parameter\nname, a "TypeError" exception is raised, unless a formal parameter\nusing the syntax "**identifier" is present; in this case, that formal\nparameter receives a dictionary containing the excess keyword\narguments (using the keywords as keys and the argument values as\ncorresponding values), or a (new) empty dictionary if there were no\nexcess keyword arguments.\n\nIf the syntax "*expression" appears in the function call, "expression"\nmust evaluate to an iterable. Elements from this iterable are treated\nas if they were additional positional arguments; if there are\npositional arguments *x1*, ..., *xN*, and "expression" evaluates to a\nsequence *y1*, ..., *yM*, this is equivalent to a call with M+N\npositional arguments *x1*, ..., *xN*, *y1*, ..., *yM*.\n\nA consequence of this is that although the "*expression" syntax may\nappear *after* some keyword arguments, it is processed *before* the\nkeyword arguments (and the "**expression" argument, if any -- see\nbelow). So:\n\n >>> def f(a, b):\n ... print(a, b)\n ...\n >>> f(b=1, *(2,))\n 2 1\n >>> f(a=1, *(2,))\n Traceback (most recent call last):\n File "", line 1, in ?\n TypeError: f() got multiple values for keyword argument \'a\'\n >>> f(1, *(2,))\n 1 2\n\nIt is unusual for both keyword arguments and the "*expression" syntax\nto be used in the same call, so in practice this confusion does not\narise.\n\nIf the syntax "**expression" appears in the function call,\n"expression" must evaluate to a mapping, the contents of which are\ntreated as additional keyword arguments. In the case of a keyword\nappearing in both "expression" and as an explicit keyword argument, a\n"TypeError" exception is raised.\n\nFormal parameters using the syntax "*identifier" or "**identifier"\ncannot be used as positional argument slots or as keyword argument\nnames.\n\nA call always returns some value, possibly "None", unless it raises an\nexception. How this value is computed depends on the type of the\ncallable object.\n\nIf it is---\n\na user-defined function:\n The code block for the function is executed, passing it the\n argument list. The first thing the code block will do is bind the\n formal parameters to the arguments; this is described in section\n *Function definitions*. When the code block executes a "return"\n statement, this specifies the return value of the function call.\n\na built-in function or method:\n The result is up to the interpreter; see *Built-in Functions* for\n the descriptions of built-in functions and methods.\n\na class object:\n A new instance of that class is returned.\n\na class instance method:\n The corresponding user-defined function is called, with an argument\n list that is one longer than the argument list of the call: the\n instance becomes the first argument.\n\na class instance:\n The class must define a "__call__()" method; the effect is then the\n same as if that method was called.\n', + 'class': '\nClass definitions\n*****************\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'comparisons': '\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. The\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of the differing types depends on whether either\nof the types provide explicit support for the comparison. Most\nnumeric types can be compared with one another. When cross-type\ncomparison is not supported, the comparison method returns\n"NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether a the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', + 'compound': '\nCompound statements\n*******************\n\nCompound statements contain (groups of) other statements; they affect\nor control the execution of those other statements in some way. In\ngeneral, compound statements span multiple lines, although in simple\nincarnations a whole compound statement may be contained in one line.\n\nThe "if", "while" and "for" statements implement traditional control\nflow constructs. "try" specifies exception handlers and/or cleanup\ncode for a group of statements, while the "with" statement allows the\nexecution of initialization and finalization code around a block of\ncode. Function and class definitions are also syntactically compound\nstatements.\n\nCompound statements consist of one or more \'clauses.\' A clause\nconsists of a header and a \'suite.\' The clause headers of a\nparticular compound statement are all at the same indentation level.\nEach clause header begins with a uniquely identifying keyword and ends\nwith a colon. A suite is a group of statements controlled by a\nclause. A suite can be one or more semicolon-separated simple\nstatements on the same line as the header, following the header\'s\ncolon, or it can be one or more indented statements on subsequent\nlines. Only the latter form of suite can contain nested compound\nstatements; the following is illegal, mostly because it wouldn\'t be\nclear to which "if" clause a following "else" clause would belong:\n\n if test1: if test2: print(x)\n\nAlso note that the semicolon binds tighter than the colon in this\ncontext, so that in the following example, either all or none of the\n"print()" calls are executed:\n\n if x < y < z: print(x); print(y); print(z)\n\nSummarizing:\n\n compound_stmt ::= if_stmt\n | while_stmt\n | for_stmt\n | try_stmt\n | with_stmt\n | funcdef\n | classdef\n suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT\n statement ::= stmt_list NEWLINE | compound_stmt\n stmt_list ::= simple_stmt (";" simple_stmt)* [";"]\n\nNote that statements always end in a "NEWLINE" possibly followed by a\n"DEDENT". Also note that optional continuation clauses always begin\nwith a keyword that cannot start a statement, thus there are no\nambiguities (the \'dangling "else"\' problem is solved in Python by\nrequiring nested "if" statements to be indented).\n\nThe formatting of the grammar rules in the following sections places\neach clause on a separate line for clarity.\n\n\nThe "if" statement\n==================\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n\n\nThe "while" statement\n=====================\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n\n\nThe "for" statement\n===================\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there was no next\nitem.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n\n\nThe "try" statement\n===================\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" target]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be access via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n def f():\n try:\n 1/0\n finally:\n return 42\n\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n\n\nThe "with" statement\n====================\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nFunction definitions\n====================\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use "None" as the default,\nand explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n\n\nClass definitions\n=================\n\nA class definition defines a class object (see section *The standard\ntype hierarchy*):\n\n classdef ::= [decorators] "class" classname [inheritance] ":" suite\n inheritance ::= "(" [parameter_list] ")"\n classname ::= identifier\n\nA class definition is an executable statement. The inheritance list\nusually gives a list of base classes (see *Customizing class creation*\nfor more advanced uses), so each item in the list should evaluate to a\nclass object which allows subclassing. Classes without an inheritance\nlist inherit, by default, from the base class "object"; hence,\n\n class Foo:\n pass\n\nis equivalent to\n\n class Foo(object):\n pass\n\nThe class\'s suite is then executed in a new execution frame (see\n*Naming and binding*), using a newly created local namespace and the\noriginal global namespace. (Usually, the suite contains mostly\nfunction definitions.) When the class\'s suite finishes execution, its\nexecution frame is discarded but its local namespace is saved. [4] A\nclass object is then created using the inheritance list for the base\nclasses and the saved local namespace for the attribute dictionary.\nThe class name is bound to this class object in the original local\nnamespace.\n\nClass creation can be customized heavily using *metaclasses*.\n\nClasses can also be decorated: just like when decorating functions,\n\n @f1(arg)\n @f2\n class Foo: pass\n\nis equivalent to\n\n class Foo: pass\n Foo = f1(arg)(f2(Foo))\n\nThe evaluation rules for the decorator expressions are the same as for\nfunction decorators. The result must be a class object, which is then\nbound to the class name.\n\n**Programmer\'s note:** Variables defined in the class definition are\nclass attributes; they are shared by instances. Instance attributes\ncan be set in a method with "self.name = value". Both class and\ninstance attributes are accessible through the notation ""self.name"",\nand an instance attribute hides a class attribute with the same name\nwhen accessed in this way. Class attributes can be used as defaults\nfor instance attributes, but using mutable values there can lead to\nunexpected results. *Descriptors* can be used to create instance\nvariables with different implementation details.\n\nSee also: **PEP 3115** - Metaclasses in Python 3 **PEP 3129** -\n Class Decorators\n\n-[ Footnotes ]-\n\n[1] The exception is propagated to the invocation stack unless\n there is a "finally" clause which happens to raise another\n exception. That new exception causes the old one to be lost.\n\n[2] Currently, control "flows off the end" except in the case of\n an exception or the execution of a "return", "continue", or\n "break" statement.\n\n[3] A string literal appearing as the first statement in the\n function body is transformed into the function\'s "__doc__"\n attribute and therefore the function\'s *docstring*.\n\n[4] A string literal appearing as the first statement in the class\n body is transformed into the namespace\'s "__doc__" item and\n therefore the class\'s *docstring*.\n', + 'context-managers': '\nWith Statement Context Managers\n*******************************\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', + 'continue': '\nThe "continue" statement\n************************\n\n continue_stmt ::= "continue"\n\n"continue" may only occur syntactically nested in a "for" or "while"\nloop, but not nested in a function or class definition or "finally"\nclause within that loop. It continues with the next cycle of the\nnearest enclosing loop.\n\nWhen "continue" passes control out of a "try" statement with a\n"finally" clause, that "finally" clause is executed before really\nstarting the next loop cycle.\n', + 'conversions': '\nArithmetic conversions\n**********************\n\nWhen a description of an arithmetic operator below uses the phrase\n"the numeric arguments are converted to a common type," this means\nthat the operator implementation for built-in types works that way:\n\n* If either argument is a complex number, the other is converted to\n complex;\n\n* otherwise, if either argument is a floating point number, the\n other is converted to floating point;\n\n* otherwise, both must be integers and no conversion is necessary.\n\nSome additional rules apply for certain operators (e.g., a string left\nargument to the \'%\' operator). Extensions must define their own\nconversion behavior.\n', + 'customization': '\nBasic customization\n*******************\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called when the instance is created. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])". As a special constraint on\n constructors, no value may be returned; doing so will cause a\n "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing "None" in\n "sys.last_traceback". Circular references which are garbage are\n detected when the option cycle detector is enabled (it\'s on by\n default), but can only be cleaned up if there are no Python-\n level "__del__()" methods involved. Refer to the documentation\n for the "gc" module for more information about how "__del__()"\n methods are handled by the cycle detector, particularly the\n description of the "garbage" value.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)""\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable").\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n .__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n', + 'debugger': '\n"pdb" --- The Python Debugger\n*****************************\n\nThe module "pdb" defines an interactive source code debugger for\nPython programs. It supports setting (conditional) breakpoints and\nsingle stepping at the source line level, inspection of stack frames,\nsource code listing, and evaluation of arbitrary Python code in the\ncontext of any stack frame. It also supports post-mortem debugging\nand can be called under program control.\n\nThe debugger is extensible -- it is actually defined as the class\n"Pdb". This is currently undocumented but easily understood by reading\nthe source. The extension interface uses the modules "bdb" and "cmd".\n\nThe debugger\'s prompt is "(Pdb)". Typical usage to run a program under\ncontrol of the debugger is:\n\n >>> import pdb\n >>> import mymodule\n >>> pdb.run(\'mymodule.test()\')\n > (0)?()\n (Pdb) continue\n > (1)?()\n (Pdb) continue\n NameError: \'spam\'\n > (1)?()\n (Pdb)\n\nChanged in version 3.3: Tab-completion via the "readline" module is\navailable for commands and command arguments, e.g. the current global\nand local names are offered as arguments of the "print" command.\n\n"pdb.py" can also be invoked as a script to debug other scripts. For\nexample:\n\n python3 -m pdb myscript.py\n\nWhen invoked as a script, pdb will automatically enter post-mortem\ndebugging if the program being debugged exits abnormally. After post-\nmortem debugging (or after normal exit of the program), pdb will\nrestart the program. Automatic restarting preserves pdb\'s state (such\nas breakpoints) and in most cases is more useful than quitting the\ndebugger upon program\'s exit.\n\nNew in version 3.2: "pdb.py" now accepts a "-c" option that executes\ncommands as if given in a ".pdbrc" file, see *Debugger Commands*.\n\nThe typical usage to break into the debugger from a running program is\nto insert\n\n import pdb; pdb.set_trace()\n\nat the location you want to break into the debugger. You can then\nstep through the code following this statement, and continue running\nwithout the debugger using the "continue" command.\n\nThe typical usage to inspect a crashed program is:\n\n >>> import pdb\n >>> import mymodule\n >>> mymodule.test()\n Traceback (most recent call last):\n File "", line 1, in ?\n File "./mymodule.py", line 4, in test\n test2()\n File "./mymodule.py", line 3, in test2\n print(spam)\n NameError: spam\n >>> pdb.pm()\n > ./mymodule.py(3)test2()\n -> print(spam)\n (Pdb)\n\nThe module defines the following functions; each enters the debugger\nin a slightly different way:\n\npdb.run(statement, globals=None, locals=None)\n\n Execute the *statement* (given as a string or a code object) under\n debugger control. The debugger prompt appears before any code is\n executed; you can set breakpoints and type "continue", or you can\n step through the statement using "step" or "next" (all these\n commands are explained below). The optional *globals* and *locals*\n arguments specify the environment in which the code is executed; by\n default the dictionary of the module "__main__" is used. (See the\n explanation of the built-in "exec()" or "eval()" functions.)\n\npdb.runeval(expression, globals=None, locals=None)\n\n Evaluate the *expression* (given as a string or a code object)\n under debugger control. When "runeval()" returns, it returns the\n value of the expression. Otherwise this function is similar to\n "run()".\n\npdb.runcall(function, *args, **kwds)\n\n Call the *function* (a function or method object, not a string)\n with the given arguments. When "runcall()" returns, it returns\n whatever the function call returned. The debugger prompt appears\n as soon as the function is entered.\n\npdb.set_trace()\n\n Enter the debugger at the calling stack frame. This is useful to\n hard-code a breakpoint at a given point in a program, even if the\n code is not otherwise being debugged (e.g. when an assertion\n fails).\n\npdb.post_mortem(traceback=None)\n\n Enter post-mortem debugging of the given *traceback* object. If no\n *traceback* is given, it uses the one of the exception that is\n currently being handled (an exception must be being handled if the\n default is to be used).\n\npdb.pm()\n\n Enter post-mortem debugging of the traceback found in\n "sys.last_traceback".\n\nThe "run*" functions and "set_trace()" are aliases for instantiating\nthe "Pdb" class and calling the method of the same name. If you want\nto access further features, you have to do this yourself:\n\nclass class pdb.Pdb(completekey=\'tab\', stdin=None, stdout=None, skip=None, nosigint=False)\n\n "Pdb" is the debugger class.\n\n The *completekey*, *stdin* and *stdout* arguments are passed to the\n underlying "cmd.Cmd" class; see the description there.\n\n The *skip* argument, if given, must be an iterable of glob-style\n module name patterns. The debugger will not step into frames that\n originate in a module that matches one of these patterns. [1]\n\n By default, Pdb sets a handler for the SIGINT signal (which is sent\n when the user presses Ctrl-C on the console) when you give a\n "continue" command. This allows you to break into the debugger\n again by pressing Ctrl-C. If you want Pdb not to touch the SIGINT\n handler, set *nosigint* tot true.\n\n Example call to enable tracing with *skip*:\n\n import pdb; pdb.Pdb(skip=[\'django.*\']).set_trace()\n\n New in version 3.1: The *skip* argument.\n\n New in version 3.2: The *nosigint* argument. Previously, a SIGINT\n handler was never set by Pdb.\n\n run(statement, globals=None, locals=None)\n runeval(expression, globals=None, locals=None)\n runcall(function, *args, **kwds)\n set_trace()\n\n See the documentation for the functions explained above.\n\n\nDebugger Commands\n=================\n\nThe commands recognized by the debugger are listed below. Most\ncommands can be abbreviated to one or two letters as indicated; e.g.\n"h(elp)" means that either "h" or "help" can be used to enter the help\ncommand (but not "he" or "hel", nor "H" or "Help" or "HELP").\nArguments to commands must be separated by whitespace (spaces or\ntabs). Optional arguments are enclosed in square brackets ("[]") in\nthe command syntax; the square brackets must not be typed.\nAlternatives in the command syntax are separated by a vertical bar\n("|").\n\nEntering a blank line repeats the last command entered. Exception: if\nthe last command was a "list" command, the next 11 lines are listed.\n\nCommands that the debugger doesn\'t recognize are assumed to be Python\nstatements and are executed in the context of the program being\ndebugged. Python statements can also be prefixed with an exclamation\npoint ("!"). This is a powerful way to inspect the program being\ndebugged; it is even possible to change a variable or call a function.\nWhen an exception occurs in such a statement, the exception name is\nprinted but the debugger\'s state is not changed.\n\nThe debugger supports *aliases*. Aliases can have parameters which\nallows one a certain level of adaptability to the context under\nexamination.\n\nMultiple commands may be entered on a single line, separated by ";;".\n(A single ";" is not used as it is the separator for multiple commands\nin a line that is passed to the Python parser.) No intelligence is\napplied to separating the commands; the input is split at the first\n";;" pair, even if it is in the middle of a quoted string.\n\nIf a file ".pdbrc" exists in the user\'s home directory or in the\ncurrent directory, it is read in and executed as if it had been typed\nat the debugger prompt. This is particularly useful for aliases. If\nboth files exist, the one in the home directory is read first and\naliases defined there can be overridden by the local file.\n\nChanged in version 3.2: ".pdbrc" can now contain commands that\ncontinue debugging, such as "continue" or "next". Previously, these\ncommands had no effect.\n\nh(elp) [command]\n\n Without argument, print the list of available commands. With a\n *command* as argument, print help about that command. "help pdb"\n displays the full documentation (the docstring of the "pdb"\n module). Since the *command* argument must be an identifier, "help\n exec" must be entered to get help on the "!" command.\n\nw(here)\n\n Print a stack trace, with the most recent frame at the bottom. An\n arrow indicates the current frame, which determines the context of\n most commands.\n\nd(own) [count]\n\n Move the current frame *count* (default one) levels down in the\n stack trace (to a newer frame).\n\nu(p) [count]\n\n Move the current frame *count* (default one) levels up in the stack\n trace (to an older frame).\n\nb(reak) [([filename:]lineno | function) [, condition]]\n\n With a *lineno* argument, set a break there in the current file.\n With a *function* argument, set a break at the first executable\n statement within that function. The line number may be prefixed\n with a filename and a colon, to specify a breakpoint in another\n file (probably one that hasn\'t been loaded yet). The file is\n searched on "sys.path". Note that each breakpoint is assigned a\n number to which all the other breakpoint commands refer.\n\n If a second argument is present, it is an expression which must\n evaluate to true before the breakpoint is honored.\n\n Without argument, list all breaks, including for each breakpoint,\n the number of times that breakpoint has been hit, the current\n ignore count, and the associated condition if any.\n\ntbreak [([filename:]lineno | function) [, condition]]\n\n Temporary breakpoint, which is removed automatically when it is\n first hit. The arguments are the same as for "break".\n\ncl(ear) [filename:lineno | bpnumber [bpnumber ...]]\n\n With a *filename:lineno* argument, clear all the breakpoints at\n this line. With a space separated list of breakpoint numbers, clear\n those breakpoints. Without argument, clear all breaks (but first\n ask confirmation).\n\ndisable [bpnumber [bpnumber ...]]\n\n Disable the breakpoints given as a space separated list of\n breakpoint numbers. Disabling a breakpoint means it cannot cause\n the program to stop execution, but unlike clearing a breakpoint, it\n remains in the list of breakpoints and can be (re-)enabled.\n\nenable [bpnumber [bpnumber ...]]\n\n Enable the breakpoints specified.\n\nignore bpnumber [count]\n\n Set the ignore count for the given breakpoint number. If count is\n omitted, the ignore count is set to 0. A breakpoint becomes active\n when the ignore count is zero. When non-zero, the count is\n decremented each time the breakpoint is reached and the breakpoint\n is not disabled and any associated condition evaluates to true.\n\ncondition bpnumber [condition]\n\n Set a new *condition* for the breakpoint, an expression which must\n evaluate to true before the breakpoint is honored. If *condition*\n is absent, any existing condition is removed; i.e., the breakpoint\n is made unconditional.\n\ncommands [bpnumber]\n\n Specify a list of commands for breakpoint number *bpnumber*. The\n commands themselves appear on the following lines. Type a line\n containing just "end" to terminate the commands. An example:\n\n (Pdb) commands 1\n (com) print some_variable\n (com) end\n (Pdb)\n\n To remove all commands from a breakpoint, type commands and follow\n it immediately with "end"; that is, give no commands.\n\n With no *bpnumber* argument, commands refers to the last breakpoint\n set.\n\n You can use breakpoint commands to start your program up again.\n Simply use the continue command, or step, or any other command that\n resumes execution.\n\n Specifying any command resuming execution (currently continue,\n step, next, return, jump, quit and their abbreviations) terminates\n the command list (as if that command was immediately followed by\n end). This is because any time you resume execution (even with a\n simple next or step), you may encounter another breakpoint--which\n could have its own command list, leading to ambiguities about which\n list to execute.\n\n If you use the \'silent\' command in the command list, the usual\n message about stopping at a breakpoint is not printed. This may be\n desirable for breakpoints that are to print a specific message and\n then continue. If none of the other commands print anything, you\n see no sign that the breakpoint was reached.\n\ns(tep)\n\n Execute the current line, stop at the first possible occasion\n (either in a function that is called or on the next line in the\n current function).\n\nn(ext)\n\n Continue execution until the next line in the current function is\n reached or it returns. (The difference between "next" and "step"\n is that "step" stops inside a called function, while "next"\n executes called functions at (nearly) full speed, only stopping at\n the next line in the current function.)\n\nunt(il) [lineno]\n\n Without argument, continue execution until the line with a number\n greater than the current one is reached.\n\n With a line number, continue execution until a line with a number\n greater or equal to that is reached. In both cases, also stop when\n the current frame returns.\n\n Changed in version 3.2: Allow giving an explicit line number.\n\nr(eturn)\n\n Continue execution until the current function returns.\n\nc(ont(inue))\n\n Continue execution, only stop when a breakpoint is encountered.\n\nj(ump) lineno\n\n Set the next line that will be executed. Only available in the\n bottom-most frame. This lets you jump back and execute code again,\n or jump forward to skip code that you don\'t want to run.\n\n It should be noted that not all jumps are allowed -- for instance\n it is not possible to jump into the middle of a "for" loop or out\n of a "finally" clause.\n\nl(ist) [first[, last]]\n\n List source code for the current file. Without arguments, list 11\n lines around the current line or continue the previous listing.\n With "." as argument, list 11 lines around the current line. With\n one argument, list 11 lines around at that line. With two\n arguments, list the given range; if the second argument is less\n than the first, it is interpreted as a count.\n\n The current line in the current frame is indicated by "->". If an\n exception is being debugged, the line where the exception was\n originally raised or propagated is indicated by ">>", if it differs\n from the current line.\n\n New in version 3.2: The ">>" marker.\n\nll | longlist\n\n List all source code for the current function or frame.\n Interesting lines are marked as for "list".\n\n New in version 3.2.\n\na(rgs)\n\n Print the argument list of the current function.\n\np(rint) expression\n\n Evaluate the *expression* in the current context and print its\n value.\n\npp expression\n\n Like the "print" command, except the value of the expression is\n pretty-printed using the "pprint" module.\n\nwhatis expression\n\n Print the type of the *expression*.\n\nsource expression\n\n Try to get source code for the given object and display it.\n\n New in version 3.2.\n\ndisplay [expression]\n\n Display the value of the expression if it changed, each time\n execution stops in the current frame.\n\n Without expression, list all display expressions for the current\n frame.\n\n New in version 3.2.\n\nundisplay [expression]\n\n Do not display the expression any more in the current frame.\n Without expression, clear all display expressions for the current\n frame.\n\n New in version 3.2.\n\ninteract\n\n Start an interative interpreter (using the "code" module) whose\n global namespace contains all the (global and local) names found in\n the current scope.\n\n New in version 3.2.\n\nalias [name [command]]\n\n Create an alias called *name* that executes *command*. The command\n must *not* be enclosed in quotes. Replaceable parameters can be\n indicated by "%1", "%2", and so on, while "%*" is replaced by all\n the parameters. If no command is given, the current alias for\n *name* is shown. If no arguments are given, all aliases are listed.\n\n Aliases may be nested and can contain anything that can be legally\n typed at the pdb prompt. Note that internal pdb commands *can* be\n overridden by aliases. Such a command is then hidden until the\n alias is removed. Aliasing is recursively applied to the first\n word of the command line; all other words in the line are left\n alone.\n\n As an example, here are two useful aliases (especially when placed\n in the ".pdbrc" file):\n\n # Print instance variables (usage "pi classInst")\n alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k])\n # Print instance variables in self\n alias ps pi self\n\nunalias name\n\n Delete the specified alias.\n\n! statement\n\n Execute the (one-line) *statement* in the context of the current\n stack frame. The exclamation point can be omitted unless the first\n word of the statement resembles a debugger command. To set a\n global variable, you can prefix the assignment command with a\n "global" statement on the same line, e.g.:\n\n (Pdb) global list_options; list_options = [\'-l\']\n (Pdb)\n\nrun [args ...]\nrestart [args ...]\n\n Restart the debugged Python program. If an argument is supplied,\n it is split with "shlex" and the result is used as the new\n "sys.argv". History, breakpoints, actions and debugger options are\n preserved. "restart" is an alias for "run".\n\nq(uit)\n\n Quit from the debugger. The program being executed is aborted.\n\n-[ Footnotes ]-\n\n[1] Whether a frame is considered to originate in a certain module\n is determined by the "__name__" in the frame globals.\n', + 'del': '\nThe "del" statement\n*******************\n\n del_stmt ::= "del" target_list\n\nDeletion is recursively defined very similar to the way assignment is\ndefined. Rather than spelling it out in full details, here are some\nhints.\n\nDeletion of a target list recursively deletes each target, from left\nto right.\n\nDeletion of a name removes the binding of that name from the local or\nglobal namespace, depending on whether the name occurs in a "global"\nstatement in the same code block. If the name is unbound, a\n"NameError" exception will be raised.\n\nDeletion of attribute references, subscriptions and slicings is passed\nto the primary object involved; deletion of a slicing is in general\nequivalent to assignment of an empty slice of the right type (but even\nthis is determined by the sliced object).\n\nChanged in version 3.2: Previously it was illegal to delete a name\nfrom the local namespace if it occurs as a free variable in a nested\nblock.\n', 'dict': '\nDictionary displays\n*******************\n\nA dictionary display is a possibly empty series of key/datum pairs\nenclosed in curly braces:\n\n dict_display ::= "{" [key_datum_list | dict_comprehension] "}"\n key_datum_list ::= key_datum ("," key_datum)* [","]\n key_datum ::= expression ":" expression\n dict_comprehension ::= expression ":" expression comp_for\n\nA dictionary display yields a new dictionary object.\n\nIf a comma-separated sequence of key/datum pairs is given, they are\nevaluated from left to right to define the entries of the dictionary:\neach key object is used as a key into the dictionary to store the\ncorresponding datum. This means that you can specify the same key\nmultiple times in the key/datum list, and the final dictionary\'s value\nfor that key will be the last one given.\n\nA dict comprehension, in contrast to list and set comprehensions,\nneeds two expressions separated with a colon followed by the usual\n"for" and "if" clauses. When the comprehension is run, the resulting\nkey and value elements are inserted in the new dictionary in the order\nthey are produced.\n\nRestrictions on the types of the key values are listed earlier in\nsection *The standard type hierarchy*. (To summarize, the key type\nshould be *hashable*, which excludes all mutable objects.) Clashes\nbetween duplicate keys are not detected; the last datum (textually\nrightmost in the display) stored for a given key value prevails.\n', - 'dynamic-features': '\nInteraction with dynamic features\n*********************************\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- ``import *`` --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a ``SyntaxError``.\n\nThe ``eval()`` and ``exec()`` functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe ``exec()`` and ``eval()`` functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', - 'else': '\nThe ``if`` statement\n********************\n\nThe ``if`` statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the ``if`` statement is executed or evaluated).\nIf all expressions are false, the suite of the ``else`` clause, if\npresent, is executed.\n', - 'exceptions': '\nExceptions\n**********\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the ``raise`` statement. Exception\nhandlers are specified with the ``try`` ... ``except`` statement. The\n``finally`` clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n``SystemExit``.\n\nExceptions are identified by class instances. The ``except`` clause\nis selected depending on the class of the instance: it must reference\nthe class of the instance or a base class thereof. The instance can\nbe received by the handler and can carry additional information about\nthe exceptional condition.\n\nNote: Exception messages are not part of the Python API. Their contents\n may change from one version of Python to the next without warning\n and should not be relied on by code which will run under multiple\n versions of the interpreter.\n\nSee also the description of the ``try`` statement in section *The try\nstatement* and ``raise`` statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by these\n operations is not available at the time the module is compiled.\n', - 'execmodel': '\nExecution model\n***************\n\n\nNaming and binding\n==================\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions ``eval()`` and ``exec()`` is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as ``nonlocal``. If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a ``NameError`` exception is raised.\nIf the name refers to a local variable that has not been bound, a\n``UnboundLocalError`` exception is raised. ``UnboundLocalError`` is a\nsubclass of ``NameError``.\n\nThe following constructs bind names: formal parameters to functions,\n``import`` statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, ``for`` loop header, or\nafter ``as`` in a ``with`` statement or ``except`` clause. The\n``import`` statement of the form ``from ... import *`` binds all names\ndefined in the imported module, except those beginning with an\nunderscore. This form may only be used at the module level.\n\nA target occurring in a ``del`` statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the ``global`` statement occurs within a block, all uses of the\nname specified in the statement refer to the binding of that name in\nthe top-level namespace. Names are resolved in the top-level\nnamespace by searching the global namespace, i.e. the namespace of the\nmodule containing the code block, and the builtins namespace, the\nnamespace of the module ``builtins``. The global namespace is\nsearched first. If the name is not found there, the builtins\nnamespace is searched. The global statement must precede all uses of\nthe name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name ``__builtins__`` in its\nglobal namespace; this should be a dictionary or a module (in the\nlatter case the module\'s dictionary is used). By default, when in the\n``__main__`` module, ``__builtins__`` is the built-in module\n``builtins``; when in any other module, ``__builtins__`` is an alias\nfor the dictionary of the ``builtins`` module itself.\n``__builtins__`` can be set to a user-created dictionary to create a\nweak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n``__builtins__``; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should ``import``\nthe ``builtins`` module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n``__main__``.\n\nThe ``global`` statement has the same scope as a name binding\noperation in the same block. If the nearest enclosing scope for a\nfree variable contains a global statement, the free variable is\ntreated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n---------------------------------\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- ``import *`` --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a ``SyntaxError``.\n\nThe ``eval()`` and ``exec()`` functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe ``exec()`` and ``eval()`` functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the ``raise`` statement. Exception\nhandlers are specified with the ``try`` ... ``except`` statement. The\n``finally`` clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n``SystemExit``.\n\nExceptions are identified by class instances. The ``except`` clause\nis selected depending on the class of the instance: it must reference\nthe class of the instance or a base class thereof. The instance can\nbe received by the handler and can carry additional information about\nthe exceptional condition.\n\nNote: Exception messages are not part of the Python API. Their contents\n may change from one version of Python to the next without warning\n and should not be relied on by code which will run under multiple\n versions of the interpreter.\n\nSee also the description of the ``try`` statement in section *The try\nstatement* and ``raise`` statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by these\n operations is not available at the time the module is compiled.\n', - 'exprlists': '\nExpression lists\n****************\n\n expression_list ::= expression ( "," expression )* [","]\n\nAn expression list containing at least one comma yields a tuple. The\nlength of the tuple is the number of expressions in the list. The\nexpressions are evaluated from left to right.\n\nThe trailing comma is required only to create a single tuple (a.k.a. a\n*singleton*); it is optional in all other cases. A single expression\nwithout a trailing comma doesn\'t create a tuple, but rather yields the\nvalue of that expression. (To create an empty tuple, use an empty pair\nof parentheses: ``()``.)\n', - 'floating': '\nFloating point literals\n***********************\n\nFloating point literals are described by the following lexical\ndefinitions:\n\n floatnumber ::= pointfloat | exponentfloat\n pointfloat ::= [intpart] fraction | intpart "."\n exponentfloat ::= (intpart | pointfloat) exponent\n intpart ::= digit+\n fraction ::= "." digit+\n exponent ::= ("e" | "E") ["+" | "-"] digit+\n\nNote that the integer and exponent parts are always interpreted using\nradix 10. For example, ``077e010`` is legal, and denotes the same\nnumber as ``77e10``. The allowed range of floating point literals is\nimplementation-dependent. Some examples of floating point literals:\n\n 3.14 10. .001 1e100 3.14e-10 0e0\n\nNote that numeric literals do not include a sign; a phrase like ``-1``\nis actually an expression composed of the unary operator ``-`` and the\nliteral ``1``.\n', - 'for': '\nThe ``for`` statement\n*********************\n\nThe ``for`` statement is used to iterate over the elements of a\nsequence (such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n``expression_list``. The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a ``StopIteration``\nexception), the suite in the ``else`` clause, if present, is executed,\nand the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ncontinues with the next item, or with the ``else`` clause if there was\nno next item.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function ``range()`` returns an\niterator of integers suitable to emulate the effect of Pascal\'s ``for\ni := a to b do``; e.g., ``list(range(3))`` returns the list ``[0, 1,\n2]``.\n\nNote: There is a subtlety when the sequence is being modified by the loop\n (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n', - 'formatstrings': '\nFormat String Syntax\n********************\n\nThe ``str.format()`` method and the ``Formatter`` class share the same\nsyntax for format strings (although in the case of ``Formatter``,\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n``{}``. Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n``{{`` and ``}}``.\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= +\n conversion ::= "r" | "s" | "a"\n format_spec ::= \n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point ``\'!\'``, and a *format_spec*, which\nis preceded by a colon ``\':\'``. These specify a non-default format\nfor the replacement value.\n\nSee also the *Format Specification Mini-Language* section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings ``\'10\'`` or\n``\':-]\'``) within a format string. The *arg_name* can be followed by\nany number of index or attribute expressions. An expression of the\nform ``\'.name\'`` selects the named attribute using ``getattr()``,\nwhile an expression of the form ``\'[index]\'`` does an index lookup\nusing ``__getitem__()``.\n\nChanged in version 3.1: The positional argument specifiers can be\nomitted, so ``\'{} {}\'`` is equivalent to ``\'{0} {1}\'``.\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the\n``__format__()`` method of the value itself. However, in some cases\nit is desirable to force a type to be formatted as a string,\noverriding its own definition of formatting. By converting the value\nto a string before calling ``__format__()``, the normal formatting\nlogic is bypassed.\n\nThree conversion flags are currently supported: ``\'!s\'`` which calls\n``str()`` on the value, ``\'!r\'`` which calls ``repr()`` and ``\'!a\'``\nwhich calls ``ascii()``.\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n "More {!a}" # Calls ascii() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields can contain only a field\nname; conversion flags and format specifications are not allowed. The\nreplacement fields within the format_spec are substituted before the\n*format_spec* string is interpreted. This allows the formatting of a\nvalue to be dynamically specified.\n\nSee the *Format examples* section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see *Format String Syntax*). They can also be passed directly to the\nbuilt-in ``format()`` function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string (``""``) produces\nthe same result as if you had called ``str()`` on the value. A non-\nempty format string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= \n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nIf a valid *align* value is specified, it can be preceeded by a *fill*\ncharacter that can be any character and defaults to a space if\nomitted. Note that it is not possible to use ``{`` and ``}`` as *fill*\nchar while using the ``str.format()`` method; this limitation however\ndoesn\'t affect the ``format()`` function.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | ``\'<\'`` | Forces the field to be left-aligned within the available |\n | | space (this is the default for most objects). |\n +-----------+------------------------------------------------------------+\n | ``\'>\'`` | Forces the field to be right-aligned within the available |\n | | space (this is the default for numbers). |\n +-----------+------------------------------------------------------------+\n | ``\'=\'`` | Forces the padding to be placed after the sign (if any) |\n | | but before the digits. This is used for printing fields |\n | | in the form \'+000000120\'. This alignment option is only |\n | | valid for numeric types. |\n +-----------+------------------------------------------------------------+\n | ``\'^\'`` | Forces the field to be centered within the available |\n | | space. |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | ``\'+\'`` | indicates that a sign should be used for both positive as |\n | | well as negative numbers. |\n +-----------+------------------------------------------------------------+\n | ``\'-\'`` | indicates that a sign should be used only for negative |\n | | numbers (this is the default behavior). |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n | | numbers, and a minus sign on negative numbers. |\n +-----------+------------------------------------------------------------+\n\nThe ``\'#\'`` option causes the "alternate form" to be used for the\nconversion. The alternate form is defined differently for different\ntypes. This option is only valid for integer, float, complex and\nDecimal types. For integers, when binary, octal, or hexadecimal output\nis used, this option adds the prefix respective ``\'0b\'``, ``\'0o\'``, or\n``\'0x\'`` to the output value. For floats, complex and Decimal the\nalternate form causes the result of the conversion to always contain a\ndecimal-point character, even if no digits follow it. Normally, a\ndecimal-point character appears in the result of these conversions\nonly if a digit follows it. In addition, for ``\'g\'`` and ``\'G\'``\nconversions, trailing zeros are not removed from the result.\n\nThe ``\',\'`` option signals the use of a comma for a thousands\nseparator. For a locale aware separator, use the ``\'n\'`` integer\npresentation type instead.\n\nChanged in version 3.1: Added the ``\',\'`` option (see also **PEP\n378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nPreceding the *width* field by a zero (``\'0\'``) character enables\nsign-aware zero-padding for numeric types. This is equivalent to a\n*fill* character of ``\'0\'`` with an *alignment* type of ``\'=\'``.\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with ``\'f\'`` and ``\'F\'``, or before and after the decimal\npoint for a floating point value formatted with ``\'g\'`` or ``\'G\'``.\nFor non-number types the field indicates the maximum field size - in\nother words, how many characters will be used from the field content.\nThe *precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'s\'`` | String format. This is the default type for strings and |\n | | may be omitted. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'s\'``. |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'b\'`` | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | ``\'c\'`` | Character. Converts the integer to the corresponding |\n | | unicode character before printing. |\n +-----------+------------------------------------------------------------+\n | ``\'d\'`` | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | ``\'o\'`` | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | ``\'x\'`` | Hex format. Outputs the number in base 16, using lower- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | ``\'X\'`` | Hex format. Outputs the number in base 16, using upper- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | ``\'n\'`` | Number. This is the same as ``\'d\'``, except that it uses |\n | | the current locale setting to insert the appropriate |\n | | number separator characters. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'d\'``. |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except\n``\'n\'`` and None). When doing so, ``float()`` is used to convert the\ninteger to a floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'e\'`` | Exponent notation. Prints the number in scientific |\n | | notation using the letter \'e\' to indicate the exponent. |\n | | The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'E\'`` | Exponent notation. Same as ``\'e\'`` except it uses an upper |\n | | case \'E\' as the separator character. |\n +-----------+------------------------------------------------------------+\n | ``\'f\'`` | Fixed point. Displays the number as a fixed-point number. |\n | | The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'F\'`` | Fixed point. Same as ``\'f\'``, but converts ``nan`` to |\n | | ``NAN`` and ``inf`` to ``INF``. |\n +-----------+------------------------------------------------------------+\n | ``\'g\'`` | General format. For a given precision ``p >= 1``, this |\n | | rounds the number to ``p`` significant digits and then |\n | | formats the result in either fixed-point format or in |\n | | scientific notation, depending on its magnitude. The |\n | | precise rules are as follows: suppose that the result |\n | | formatted with presentation type ``\'e\'`` and precision |\n | | ``p-1`` would have exponent ``exp``. Then if ``-4 <= exp |\n | | < p``, the number is formatted with presentation type |\n | | ``\'f\'`` and precision ``p-1-exp``. Otherwise, the number |\n | | is formatted with presentation type ``\'e\'`` and precision |\n | | ``p-1``. In both cases insignificant trailing zeros are |\n | | removed from the significand, and the decimal point is |\n | | also removed if there are no remaining digits following |\n | | it. Positive and negative infinity, positive and negative |\n | | zero, and nans, are formatted as ``inf``, ``-inf``, ``0``, |\n | | ``-0`` and ``nan`` respectively, regardless of the |\n | | precision. A precision of ``0`` is treated as equivalent |\n | | to a precision of ``1``. The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'G\'`` | General format. Same as ``\'g\'`` except switches to ``\'E\'`` |\n | | if the number gets too large. The representations of |\n | | infinity and NaN are uppercased, too. |\n +-----------+------------------------------------------------------------+\n | ``\'n\'`` | Number. This is the same as ``\'g\'``, except that it uses |\n | | the current locale setting to insert the appropriate |\n | | number separator characters. |\n +-----------+------------------------------------------------------------+\n | ``\'%\'`` | Percentage. Multiplies the number by 100 and displays in |\n | | fixed (``\'f\'``) format, followed by a percent sign. |\n +-----------+------------------------------------------------------------+\n | None | Similar to ``\'g\'``, except with at least one digit past |\n | | the decimal point and a default precision of 12. This is |\n | | intended to match ``str()``, except you can add the other |\n | | format modifiers. |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the new format syntax and comparison\nwith the old ``%``-formatting.\n\nIn most of the cases the syntax is similar to the old\n``%``-formatting, with the addition of the ``{}`` and with ``:`` used\ninstead of ``%``. For example, ``\'%03.2f\'`` can be translated to\n``\'{:03.2f}\'``.\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 3.1+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point:\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing ``%s`` and ``%r``:\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing ``%x`` and ``%o`` and converting the value to different\nbases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 86.36%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12): #doctest: +NORMALIZE_WHITESPACE\n ... for base in \'dXob\':\n ... print(\'{0:{width}{base}}\'.format(num, base=base, width=width), end=\' \')\n ... print()\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n', - 'function': '\nFunction definitions\n********************\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* ``=``\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the "``*``" must also have a default value ---\nthis is a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use ``None`` as the\ndefault, and explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n"``*identifier``" is present, it is initialized to a tuple receiving\nany excess positional parameters, defaulting to the empty tuple. If\nthe form "``**identifier``" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after "``*``" or "``*identifier``" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "``: expression``"\nfollowing the parameter name. Any parameter may have an annotation\neven those of the form ``*identifier`` or ``**identifier``. Functions\nmay have "return" annotation of the form "``-> expression``" after the\nparameter list. These annotations can be any valid Python expression\nand are evaluated when the function definition is executed.\nAnnotations may be evaluated in a different order than they appear in\nthe source code. The presence of annotations does not change the\nsemantics of a function. The annotation values are available as\nvalues of a dictionary keyed by the parameters\' names in the\n``__annotations__`` attribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a "``def``" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The "``def``" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A "``def``"\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also:\n\n **PEP 3107** - Function Annotations\n The original specification for function annotations.\n', - 'global': '\nThe ``global`` statement\n************************\n\n global_stmt ::= "global" identifier ("," identifier)*\n\nThe ``global`` statement is a declaration which holds for the entire\ncurrent code block. It means that the listed identifiers are to be\ninterpreted as globals. It would be impossible to assign to a global\nvariable without ``global``, although free variables may refer to\nglobals without being declared global.\n\nNames listed in a ``global`` statement must not be used in the same\ncode block textually preceding that ``global`` statement.\n\nNames listed in a ``global`` statement must not be defined as formal\nparameters or in a ``for`` loop control target, ``class`` definition,\nfunction definition, or ``import`` statement.\n\n**CPython implementation detail:** The current implementation does not\nenforce the latter two restrictions, but programs should not abuse\nthis freedom, as future implementations may enforce them or silently\nchange the meaning of the program.\n\n**Programmer\'s note:** the ``global`` is a directive to the parser.\nIt applies only to code parsed at the same time as the ``global``\nstatement. In particular, a ``global`` statement contained in a string\nor code object supplied to the built-in ``exec()`` function does not\naffect the code block *containing* the function call, and code\ncontained in such a string is unaffected by ``global`` statements in\nthe code containing the function call. The same applies to the\n``eval()`` and ``compile()`` functions.\n', - 'id-classes': '\nReserved classes of identifiers\n*******************************\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n``_*``\n Not imported by ``from module import *``. The special identifier\n ``_`` is used in the interactive interpreter to store the result of\n the last evaluation; it is stored in the ``builtins`` module. When\n not in interactive mode, ``_`` has no special meaning and is not\n defined. See section *The import statement*.\n\n Note: The name ``_`` is often used in conjunction with\n internationalization; refer to the documentation for the\n ``gettext`` module for more information on this convention.\n\n``__*__``\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of ``__*__`` names, in any context, that does\n not follow explicitly documented use, is subject to breakage\n without warning.\n\n``__*``\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', - 'identifiers': '\nIdentifiers and keywords\n************************\n\nIdentifiers (also referred to as *names*) are described by the\nfollowing lexical definitions.\n\nThe syntax of identifiers in Python is based on the Unicode standard\nannex UAX-31, with elaboration and changes as defined below; see also\n**PEP 3131** for further details.\n\nWithin the ASCII range (U+0001..U+007F), the valid characters for\nidentifiers are the same as in Python 2.x: the uppercase and lowercase\nletters ``A`` through ``Z``, the underscore ``_`` and, except for the\nfirst character, the digits ``0`` through ``9``.\n\nPython 3.0 introduces additional characters from outside the ASCII\nrange (see **PEP 3131**). For these characters, the classification\nuses the version of the Unicode Character Database as included in the\n``unicodedata`` module.\n\nIdentifiers are unlimited in length. Case is significant.\n\n identifier ::= xid_start xid_continue*\n id_start ::= \n id_continue ::= \n xid_start ::= \n xid_continue ::= \n\nThe Unicode category codes mentioned above stand for:\n\n* *Lu* - uppercase letters\n\n* *Ll* - lowercase letters\n\n* *Lt* - titlecase letters\n\n* *Lm* - modifier letters\n\n* *Lo* - other letters\n\n* *Nl* - letter numbers\n\n* *Mn* - nonspacing marks\n\n* *Mc* - spacing combining marks\n\n* *Nd* - decimal numbers\n\n* *Pc* - connector punctuations\n\n* *Other_ID_Start* - explicit list of characters in PropList.txt to\n support backwards compatibility\n\n* *Other_ID_Continue* - likewise\n\nAll identifiers are converted into the normal form NFKC while parsing;\ncomparison of identifiers is based on NFKC.\n\nA non-normative HTML file listing all valid identifier characters for\nUnicode 4.1 can be found at http://www.dcl.hpi.uni-\npotsdam.de/home/loewis/table-3131.html.\n\n\nKeywords\n========\n\nThe following identifiers are used as reserved words, or *keywords* of\nthe language, and cannot be used as ordinary identifiers. They must\nbe spelled exactly as written here:\n\n False class finally is return\n None continue for lambda try\n True def from nonlocal while\n and del global not with\n as elif if or yield\n assert else import pass\n break except in raise\n\n\nReserved classes of identifiers\n===============================\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n``_*``\n Not imported by ``from module import *``. The special identifier\n ``_`` is used in the interactive interpreter to store the result of\n the last evaluation; it is stored in the ``builtins`` module. When\n not in interactive mode, ``_`` has no special meaning and is not\n defined. See section *The import statement*.\n\n Note: The name ``_`` is often used in conjunction with\n internationalization; refer to the documentation for the\n ``gettext`` module for more information on this convention.\n\n``__*__``\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of ``__*__`` names, in any context, that does\n not follow explicitly documented use, is subject to breakage\n without warning.\n\n``__*``\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', - 'if': '\nThe ``if`` statement\n********************\n\nThe ``if`` statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the ``if`` statement is executed or evaluated).\nIf all expressions are false, the suite of the ``else`` clause, if\npresent, is executed.\n', - 'imaginary': '\nImaginary literals\n******************\n\nImaginary literals are described by the following lexical definitions:\n\n imagnumber ::= (floatnumber | intpart) ("j" | "J")\n\nAn imaginary literal yields a complex number with a real part of 0.0.\nComplex numbers are represented as a pair of floating point numbers\nand have the same restrictions on their range. To create a complex\nnumber with a nonzero real part, add a floating point number to it,\ne.g., ``(3+4j)``. Some examples of imaginary literals:\n\n 3.14j 10.j 10j .001j 1e100j 3.14e-10j\n', - 'import': '\nThe ``import`` statement\n************************\n\n import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*\n | "from" relative_module "import" identifier ["as" name]\n ( "," identifier ["as" name] )*\n | "from" relative_module "import" "(" identifier ["as" name]\n ( "," identifier ["as" name] )* [","] ")"\n | "from" module "import" "*"\n module ::= (identifier ".")* identifier\n relative_module ::= "."* module | "."+\n name ::= identifier\n\nThe basic import statement (no ``from`` clause) is executed in two\nsteps:\n\n1. find a module, loading and initializing it if necessary\n\n2. define a name or names in the local namespace for the scope where\n the ``import`` statement occurs.\n\nWhen the statement contains multiple clauses (separated by commas) the\ntwo steps are carried out separately for each clause, just as though\nthe clauses had been separated out into individiual import statements.\n\nThe details of the first step, finding and loading modules is\ndescribed in greater detail in the section on the *import system*,\nwhich also describes the various types of packages and modules that\ncan be imported, as well as all the hooks that can be used to\ncustomize the import system. Note that failures in this step may\nindicate either that the module could not be located, *or* that an\nerror occurred while initializing the module, which includes execution\nof the module\'s code.\n\nIf the requested module is retrieved successfully, it will be made\navailable in the local namespace in one of three ways:\n\n* If the module name is followed by ``as``, then the name following\n ``as`` is bound directly to the imported module.\n\n* If no other name is specified, and the module being imported is a\n top level module, the module\'s name is bound in the local namespace\n as a reference to the imported module\n\n* If the module being imported is *not* a top level module, then the\n name of the top level package that contains the module is bound in\n the local namespace as a reference to the top level package. The\n imported module must be accessed using its full qualified name\n rather than directly\n\nThe ``from`` form uses a slightly more complex process:\n\n1. find the module specified in the ``from`` clause loading and\n initializing it if necessary;\n\n2. for each of the identifiers specified in the ``import`` clauses:\n\n 1. check if the imported module has an attribute by that name\n\n 2. if not, attempt to import a submodule with that name and then\n check the imported module again for that attribute\n\n 3. if the attribute is not found, ``ImportError`` is raised.\n\n 4. otherwise, a reference to that value is bound in the local\n namespace, using the name in the ``as`` clause if it is present,\n otherwise using the attribute name\n\nExamples:\n\n import foo # foo imported and bound locally\n import foo.bar.baz # foo.bar.baz imported, foo bound locally\n import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb\n from foo.bar import baz # foo.bar.baz imported and bound as baz\n from foo import attr # foo imported and foo.attr bound as attr\n\nIf the list of identifiers is replaced by a star (``\'*\'``), all public\nnames defined in the module are bound in the local namespace for the\nscope where the ``import`` statement occurs.\n\nThe *public names* defined by a module are determined by checking the\nmodule\'s namespace for a variable named ``__all__``; if defined, it\nmust be a sequence of strings which are names defined or imported by\nthat module. The names given in ``__all__`` are all considered public\nand are required to exist. If ``__all__`` is not defined, the set of\npublic names includes all names found in the module\'s namespace which\ndo not begin with an underscore character (``\'_\'``). ``__all__``\nshould contain the entire public API. It is intended to avoid\naccidentally exporting items that are not part of the API (such as\nlibrary modules which were imported and used within the module).\n\nThe ``from`` form with ``*`` may only occur in a module scope. The\nwild card form of import --- ``import *`` --- is only allowed at the\nmodule level. Attempting to use it in class or function definitions\nwill raise a ``SyntaxError``.\n\nWhen specifying what module to import you do not have to specify the\nabsolute name of the module. When a module or package is contained\nwithin another package it is possible to make a relative import within\nthe same top package without having to mention the package name. By\nusing leading dots in the specified module or package after ``from``\nyou can specify how high to traverse up the current package hierarchy\nwithout specifying exact names. One leading dot means the current\npackage where the module making the import exists. Two dots means up\none package level. Three dots is up two levels, etc. So if you execute\n``from . import mod`` from a module in the ``pkg`` package then you\nwill end up importing ``pkg.mod``. If you execute ``from ..subpkg2\nimport mod`` from within ``pkg.subpkg1`` you will import\n``pkg.subpkg2.mod``. The specification for relative imports is\ncontained within **PEP 328**.\n\n``importlib.import_module()`` is provided to support applications that\ndetermine which modules need to be loaded dynamically.\n\n\nFuture statements\n=================\n\nA *future statement* is a directive to the compiler that a particular\nmodule should be compiled using syntax or semantics that will be\navailable in a specified future release of Python. The future\nstatement is intended to ease migration to future versions of Python\nthat introduce incompatible changes to the language. It allows use of\nthe new features on a per-module basis before the release in which the\nfeature becomes standard.\n\n future_statement ::= "from" "__future__" "import" feature ["as" name]\n ("," feature ["as" name])*\n | "from" "__future__" "import" "(" feature ["as" name]\n ("," feature ["as" name])* [","] ")"\n feature ::= identifier\n name ::= identifier\n\nA future statement must appear near the top of the module. The only\nlines that can appear before a future statement are:\n\n* the module docstring (if any),\n\n* comments,\n\n* blank lines, and\n\n* other future statements.\n\nThe features recognized by Python 3.0 are ``absolute_import``,\n``division``, ``generators``, ``unicode_literals``,\n``print_function``, ``nested_scopes`` and ``with_statement``. They\nare all redundant because they are always enabled, and only kept for\nbackwards compatibility.\n\nA future statement is recognized and treated specially at compile\ntime: Changes to the semantics of core constructs are often\nimplemented by generating different code. It may even be the case\nthat a new feature introduces new incompatible syntax (such as a new\nreserved word), in which case the compiler may need to parse the\nmodule differently. Such decisions cannot be pushed off until\nruntime.\n\nFor any given release, the compiler knows which feature names have\nbeen defined, and raises a compile-time error if a future statement\ncontains a feature not known to it.\n\nThe direct runtime semantics are the same as for any import statement:\nthere is a standard module ``__future__``, described later, and it\nwill be imported in the usual way at the time the future statement is\nexecuted.\n\nThe interesting runtime semantics depend on the specific feature\nenabled by the future statement.\n\nNote that there is nothing special about the statement:\n\n import __future__ [as name]\n\nThat is not a future statement; it\'s an ordinary import statement with\nno special semantics or syntax restrictions.\n\nCode compiled by calls to the built-in functions ``exec()`` and\n``compile()`` that occur in a module ``M`` containing a future\nstatement will, by default, use the new syntax or semantics associated\nwith the future statement. This can be controlled by optional\narguments to ``compile()`` --- see the documentation of that function\nfor details.\n\nA future statement typed at an interactive interpreter prompt will\ntake effect for the rest of the interpreter session. If an\ninterpreter is started with the *-i* option, is passed a script name\nto execute, and the script includes a future statement, it will be in\neffect in the interactive session started after the script is\nexecuted.\n\nSee also:\n\n **PEP 236** - Back to the __future__\n The original proposal for the __future__ mechanism.\n', - 'in': '\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like ``a < b < c`` have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: ``True`` or ``False``.\n\nComparisons can be chained arbitrarily, e.g., ``x < y <= z`` is\nequivalent to ``x < y and y <= z``, except that ``y`` is evaluated\nonly once (but in both cases ``z`` is not evaluated at all when ``x <\ny`` is found to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then ``a op1 b op2 c ... y\nopN z`` is equivalent to ``a op1 b and b op2 c and ... y opN z``,\nexcept that each expression is evaluated at most once.\n\nNote that ``a op1 b op2 c`` doesn\'t imply any kind of comparison\nbetween *a* and *c*, so that, e.g., ``x < y > z`` is perfectly legal\n(though perhaps not pretty).\n\nThe operators ``<``, ``>``, ``==``, ``>=``, ``<=``, and ``!=`` compare\nthe values of two objects. The objects need not have the same type.\nIf both are numbers, they are converted to a common type. Otherwise,\nthe ``==`` and ``!=`` operators *always* consider objects of different\ntypes to be unequal, while the ``<``, ``>``, ``>=`` and ``<=``\noperators raise a ``TypeError`` when comparing objects of different\ntypes that do not implement these operators for the given pair of\ntypes. You can control comparison behavior of objects of non-built-in\ntypes by defining rich comparison methods like ``__gt__()``, described\nin section *Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values ``float(\'NaN\')`` and ``Decimal(\'NaN\')`` are special. The\n are identical to themselves, ``x is x`` but are not equal to\n themselves, ``x != x``. Additionally, comparing any value to a\n not-a-number value will return ``False``. For example, both ``3 <\n float(\'NaN\')`` and ``float(\'NaN\') < 3`` will return ``False``.\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric equivalents\n (the result of the built-in function ``ord()``) of their characters.\n [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison of\n corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, ``[1,2,x] <= [1,2,y]`` has the\n same value as ``x <= y``. If the corresponding element does not\n exist, the shorter sequence is ordered first (for example, ``[1,2] <\n [1,2,3]``).\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same ``(key, value)`` pairs. Order comparisons ``(\'<\', \'<=\', \'>=\',\n \'>\')`` raise ``TypeError``.\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets ``{1,2}`` and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, ``min()``, ``max()``, and ``sorted()`` produce\n undefined results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they are\n the same object; the choice whether one object is considered smaller\n or larger than another one is made arbitrarily but consistently\n within one execution of a program.\n\nComparison of objects of the differing types depends on whether either\nof the types provide explicit support for the comparison. Most\nnumeric types can be compared with one another. When cross-type\ncomparison is not supported, the comparison method returns\n``NotImplemented``.\n\nThe operators ``in`` and ``not in`` test for membership. ``x in s``\nevaluates to true if *x* is a member of *s*, and false otherwise. ``x\nnot in s`` returns the negation of ``x in s``. All built-in sequences\nand set types support this as well as dictionary, for which ``in``\ntests whether a the dictionary has a given key. For container types\nsuch as list, tuple, set, frozenset, dict, or collections.deque, the\nexpression ``x in y`` is equivalent to ``any(x is e or x == e for e in\ny)``.\n\nFor the string and bytes types, ``x in y`` is true if and only if *x*\nis a substring of *y*. An equivalent test is ``y.find(x) != -1``.\nEmpty strings are always considered to be a substring of any other\nstring, so ``"" in "abc"`` will return ``True``.\n\nFor user-defined classes which define the ``__contains__()`` method,\n``x in y`` is true if and only if ``y.__contains__(x)`` is true.\n\nFor user-defined classes which do not define ``__contains__()`` but do\ndefine ``__iter__()``, ``x in y`` is true if some value ``z`` with ``x\n== z`` is produced while iterating over ``y``. If an exception is\nraised during the iteration, it is as if ``in`` raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n``__getitem__()``, ``x in y`` is true if and only if there is a non-\nnegative integer index *i* such that ``x == y[i]``, and all lower\ninteger indices do not raise ``IndexError`` exception. (If any other\nexception is raised, it is as if ``in`` raised that exception).\n\nThe operator ``not in`` is defined to have the inverse true value of\n``in``.\n\nThe operators ``is`` and ``is not`` test for object identity: ``x is\ny`` is true if and only if *x* and *y* are the same object. ``x is\nnot y`` yields the inverse truth value. [4]\n', + 'dynamic-features': '\nInteraction with dynamic features\n*********************************\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', + 'else': '\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', + 'exceptions': '\nExceptions\n**********\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', + 'execmodel': '\nExecution model\n***************\n\n\nNaming and binding\n==================\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal". If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, a\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\nglobal statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n---------------------------------\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the "raise" statement. Exception\nhandlers are specified with the "try" ... "except" statement. The\n"finally" clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n"SystemExit".\n\nExceptions are identified by class instances. The "except" clause is\nselected depending on the class of the instance: it must reference the\nclass of the instance or a base class thereof. The instance can be\nreceived by the handler and can carry additional information about the\nexceptional condition.\n\nNote: Exception messages are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the "try" statement in section *The try\nstatement* and "raise" statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by\n these operations is not available at the time the module is\n compiled.\n', + 'exprlists': '\nExpression lists\n****************\n\n expression_list ::= expression ( "," expression )* [","]\n\nAn expression list containing at least one comma yields a tuple. The\nlength of the tuple is the number of expressions in the list. The\nexpressions are evaluated from left to right.\n\nThe trailing comma is required only to create a single tuple (a.k.a. a\n*singleton*); it is optional in all other cases. A single expression\nwithout a trailing comma doesn\'t create a tuple, but rather yields the\nvalue of that expression. (To create an empty tuple, use an empty pair\nof parentheses: "()".)\n', + 'floating': '\nFloating point literals\n***********************\n\nFloating point literals are described by the following lexical\ndefinitions:\n\n floatnumber ::= pointfloat | exponentfloat\n pointfloat ::= [intpart] fraction | intpart "."\n exponentfloat ::= (intpart | pointfloat) exponent\n intpart ::= digit+\n fraction ::= "." digit+\n exponent ::= ("e" | "E") ["+" | "-"] digit+\n\nNote that the integer and exponent parts are always interpreted using\nradix 10. For example, "077e010" is legal, and denotes the same number\nas "77e10". The allowed range of floating point literals is\nimplementation-dependent. Some examples of floating point literals:\n\n 3.14 10. .001 1e100 3.14e-10 0e0\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator "-" and the\nliteral "1".\n', + 'for': '\nThe "for" statement\n*******************\n\nThe "for" statement is used to iterate over the elements of a sequence\n(such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n"expression_list". The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments (see *Assignment statements*), and then the suite is\nexecuted. When the items are exhausted (which is immediately when the\nsequence is empty or an iterator raises a "StopIteration" exception),\nthe suite in the "else" clause, if present, is executed, and the loop\nterminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and continues\nwith the next item, or with the "else" clause if there was no next\nitem.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nNames in the target list are not deleted when the loop is finished,\nbut if the sequence is empty, it will not have been assigned to at all\nby the loop. Hint: the built-in function "range()" returns an\niterator of integers suitable to emulate the effect of Pascal\'s "for i\n:= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n\nNote: There is a subtlety when the sequence is being modified by the\n loop (this can only occur for mutable sequences, i.e. lists). An\n internal counter is used to keep track of which item is used next,\n and this is incremented on each iteration. When this counter has\n reached the length of the sequence the loop terminates. This means\n that if the suite deletes the current (or a previous) item from the\n sequence, the next item will be skipped (since it gets the index of\n the current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n', + 'formatstrings': '\nFormat String Syntax\n********************\n\nThe "str.format()" method and the "Formatter" class share the same\nsyntax for format strings (although in the case of "Formatter",\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n"{}". Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n"{{" and "}}".\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= +\n conversion ::= "r" | "s" | "a"\n format_spec ::= \n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point "\'!\'", and a *format_spec*, which is\npreceded by a colon "\':\'". These specify a non-default format for the\nreplacement value.\n\nSee also the *Format Specification Mini-Language* section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings "\'10\'" or\n"\':-]\'") within a format string. The *arg_name* can be followed by any\nnumber of index or attribute expressions. An expression of the form\n"\'.name\'" selects the named attribute using "getattr()", while an\nexpression of the form "\'[index]\'" does an index lookup using\n"__getitem__()".\n\nChanged in version 3.1: The positional argument specifiers can be\nomitted, so "\'{} {}\'" is equivalent to "\'{0} {1}\'".\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the "__format__()"\nmethod of the value itself. However, in some cases it is desirable to\nforce a type to be formatted as a string, overriding its own\ndefinition of formatting. By converting the value to a string before\ncalling "__format__()", the normal formatting logic is bypassed.\n\nThree conversion flags are currently supported: "\'!s\'" which calls\n"str()" on the value, "\'!r\'" which calls "repr()" and "\'!a\'" which\ncalls "ascii()".\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n "More {!a}" # Calls ascii() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields can contain only a field\nname; conversion flags and format specifications are not allowed. The\nreplacement fields within the format_spec are substituted before the\n*format_spec* string is interpreted. This allows the formatting of a\nvalue to be dynamically specified.\n\nSee the *Format examples* section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see *Format String Syntax*). They can also be passed directly to the\nbuilt-in "format()" function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string ("""") produces\nthe same result as if you had called "str()" on the value. A non-empty\nformat string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= \n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nIf a valid *align* value is specified, it can be preceded by a *fill*\ncharacter that can be any character and defaults to a space if\nomitted. Note that it is not possible to use "{" and "}" as *fill*\nchar while using the "str.format()" method; this limitation however\ndoesn\'t affect the "format()" function.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'<\'" | Forces the field to be left-aligned within the available |\n +-----------+------------------------------------------------------------+\n | "\'>\'" | Forces the field to be right-aligned within the available |\n +-----------+------------------------------------------------------------+\n | "\'=\'" | Forces the padding to be placed after the sign (if any) |\n +-----------+------------------------------------------------------------+\n | "\'^\'" | Forces the field to be centered within the available |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | "\'+\'" | indicates that a sign should be used for both positive as |\n +-----------+------------------------------------------------------------+\n | "\'-\'" | indicates that a sign should be used only for negative |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n +-----------+------------------------------------------------------------+\n\nThe "\'#\'" option causes the "alternate form" to be used for the\nconversion. The alternate form is defined differently for different\ntypes. This option is only valid for integer, float, complex and\nDecimal types. For integers, when binary, octal, or hexadecimal output\nis used, this option adds the prefix respective "\'0b\'", "\'0o\'", or\n"\'0x\'" to the output value. For floats, complex and Decimal the\nalternate form causes the result of the conversion to always contain a\ndecimal-point character, even if no digits follow it. Normally, a\ndecimal-point character appears in the result of these conversions\nonly if a digit follows it. In addition, for "\'g\'" and "\'G\'"\nconversions, trailing zeros are not removed from the result.\n\nThe "\',\'" option signals the use of a comma for a thousands separator.\nFor a locale aware separator, use the "\'n\'" integer presentation type\ninstead.\n\nChanged in version 3.1: Added the "\',\'" option (see also **PEP 378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nPreceding the *width* field by a zero ("\'0\'") character enables sign-\naware zero-padding for numeric types. This is equivalent to a *fill*\ncharacter of "\'0\'" with an *alignment* type of "\'=\'".\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with "\'f\'" and "\'F\'", or before and after the decimal point\nfor a floating point value formatted with "\'g\'" or "\'G\'". For non-\nnumber types the field indicates the maximum field size - in other\nwords, how many characters will be used from the field content. The\n*precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'s\'" | String format. This is the default type for strings and |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'s\'". |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'b\'" | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | "\'c\'" | Character. Converts the integer to the corresponding |\n +-----------+------------------------------------------------------------+\n | "\'d\'" | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | "\'o\'" | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | "\'x\'" | Hex format. Outputs the number in base 16, using lower- |\n +-----------+------------------------------------------------------------+\n | "\'X\'" | Hex format. Outputs the number in base 16, using upper- |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'d\'", except that it uses the |\n +-----------+------------------------------------------------------------+\n | None | The same as "\'d\'". |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except "\'n\'"\nand None). When doing so, "float()" is used to convert the integer to\na floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | "\'e\'" | Exponent notation. Prints the number in scientific |\n +-----------+------------------------------------------------------------+\n | "\'E\'" | Exponent notation. Same as "\'e\'" except it uses an upper |\n +-----------+------------------------------------------------------------+\n | "\'f\'" | Fixed point. Displays the number as a fixed-point number. |\n +-----------+------------------------------------------------------------+\n | "\'F\'" | Fixed point. Same as "\'f\'", but converts "nan" to "NAN" |\n +-----------+------------------------------------------------------------+\n | "\'g\'" | General format. For a given precision "p >= 1", this |\n +-----------+------------------------------------------------------------+\n | "\'G\'" | General format. Same as "\'g\'" except switches to "\'E\'" if |\n +-----------+------------------------------------------------------------+\n | "\'n\'" | Number. This is the same as "\'g\'", except that it uses the |\n +-----------+------------------------------------------------------------+\n | "\'%\'" | Percentage. Multiplies the number by 100 and displays in |\n +-----------+------------------------------------------------------------+\n | None | Similar to "\'g\'", except with at least one digit past the |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the new format syntax and comparison\nwith the old "%"-formatting.\n\nIn most of the cases the syntax is similar to the old "%"-formatting,\nwith the addition of the "{}" and with ":" used instead of "%". For\nexample, "\'%03.2f\'" can be translated to "\'{:03.2f}\'".\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 3.1+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point:\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing "%s" and "%r":\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing "%+f", "%-f", and "% f" and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing "%x" and "%o" and converting the value to different bases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 86.36%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12): #doctest: +NORMALIZE_WHITESPACE\n ... for base in \'dXob\':\n ... print(\'{0:{width}{base}}\'.format(num, base=base, width=width), end=\' \')\n ... print()\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n', + 'function': '\nFunction definitions\n********************\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [parameter_list [","]] ")"] NEWLINE\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" [parameter] ("," defparameter)* ["," "**" parameter]\n | "**" parameter\n | defparameter [","] )\n parameter ::= identifier [":" expression]\n defparameter ::= parameter ["=" expression]\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more *parameters* have the form *parameter* "="\n*expression*, the function is said to have "default parameter values."\nFor a parameter with a default value, the corresponding *argument* may\nbe omitted from a call, in which case the parameter\'s default value is\nsubstituted. If a parameter has a default value, all following\nparameters up until the ""*"" must also have a default value --- this\nis a syntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use "None" as the default,\nand explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n""*identifier"" is present, it is initialized to a tuple receiving any\nexcess positional parameters, defaulting to the empty tuple. If the\nform ""**identifier"" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary. Parameters after ""*"" or ""*identifier"" are\nkeyword-only parameters and may only be passed used keyword arguments.\n\nParameters may have annotations of the form "": expression"" following\nthe parameter name. Any parameter may have an annotation even those\nof the form "*identifier" or "**identifier". Functions may have\n"return" annotation of the form ""-> expression"" after the parameter\nlist. These annotations can be any valid Python expression and are\nevaluated when the function definition is executed. Annotations may\nbe evaluated in a different order than they appear in the source code.\nThe presence of annotations does not change the semantics of a\nfunction. The annotation values are available as values of a\ndictionary keyed by the parameters\' names in the "__annotations__"\nattribute of the function object.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a ""def"" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The ""def"" form is actually more powerful since it\nallows the execution of multiple statements and annotations.\n\n**Programmer\'s note:** Functions are first-class objects. A ""def""\nstatement executed inside a function definition defines a local\nfunction that can be returned or passed around. Free variables used\nin the nested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n\nSee also: **PEP 3107** - Function Annotations\n\n The original specification for function annotations.\n', + 'global': '\nThe "global" statement\n**********************\n\n global_stmt ::= "global" identifier ("," identifier)*\n\nThe "global" statement is a declaration which holds for the entire\ncurrent code block. It means that the listed identifiers are to be\ninterpreted as globals. It would be impossible to assign to a global\nvariable without "global", although free variables may refer to\nglobals without being declared global.\n\nNames listed in a "global" statement must not be used in the same code\nblock textually preceding that "global" statement.\n\nNames listed in a "global" statement must not be defined as formal\nparameters or in a "for" loop control target, "class" definition,\nfunction definition, or "import" statement.\n\n**CPython implementation detail:** The current implementation does not\nenforce the latter two restrictions, but programs should not abuse\nthis freedom, as future implementations may enforce them or silently\nchange the meaning of the program.\n\n**Programmer\'s note:** the "global" is a directive to the parser. It\napplies only to code parsed at the same time as the "global"\nstatement. In particular, a "global" statement contained in a string\nor code object supplied to the built-in "exec()" function does not\naffect the code block *containing* the function call, and code\ncontained in such a string is unaffected by "global" statements in the\ncode containing the function call. The same applies to the "eval()"\nand "compile()" functions.\n', + 'id-classes': '\nReserved classes of identifiers\n*******************************\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "builtins" module. When not\n in interactive mode, "_" has no special meaning and is not defined.\n See section *The import statement*.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', + 'identifiers': '\nIdentifiers and keywords\n************************\n\nIdentifiers (also referred to as *names*) are described by the\nfollowing lexical definitions.\n\nThe syntax of identifiers in Python is based on the Unicode standard\nannex UAX-31, with elaboration and changes as defined below; see also\n**PEP 3131** for further details.\n\nWithin the ASCII range (U+0001..U+007F), the valid characters for\nidentifiers are the same as in Python 2.x: the uppercase and lowercase\nletters "A" through "Z", the underscore "_" and, except for the first\ncharacter, the digits "0" through "9".\n\nPython 3.0 introduces additional characters from outside the ASCII\nrange (see **PEP 3131**). For these characters, the classification\nuses the version of the Unicode Character Database as included in the\n"unicodedata" module.\n\nIdentifiers are unlimited in length. Case is significant.\n\n identifier ::= xid_start xid_continue*\n id_start ::= \n id_continue ::= \n xid_start ::= \n xid_continue ::= \n\nThe Unicode category codes mentioned above stand for:\n\n* *Lu* - uppercase letters\n\n* *Ll* - lowercase letters\n\n* *Lt* - titlecase letters\n\n* *Lm* - modifier letters\n\n* *Lo* - other letters\n\n* *Nl* - letter numbers\n\n* *Mn* - nonspacing marks\n\n* *Mc* - spacing combining marks\n\n* *Nd* - decimal numbers\n\n* *Pc* - connector punctuations\n\n* *Other_ID_Start* - explicit list of characters in PropList.txt to\n support backwards compatibility\n\n* *Other_ID_Continue* - likewise\n\nAll identifiers are converted into the normal form NFKC while parsing;\ncomparison of identifiers is based on NFKC.\n\nA non-normative HTML file listing all valid identifier characters for\nUnicode 4.1 can be found at http://www.dcl.hpi.uni-\npotsdam.de/home/loewis/table-3131.html.\n\n\nKeywords\n========\n\nThe following identifiers are used as reserved words, or *keywords* of\nthe language, and cannot be used as ordinary identifiers. They must\nbe spelled exactly as written here:\n\n False class finally is return\n None continue for lambda try\n True def from nonlocal while\n and del global not with\n as elif if or yield\n assert else import pass\n break except in raise\n\n\nReserved classes of identifiers\n===============================\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n"_*"\n Not imported by "from module import *". The special identifier "_"\n is used in the interactive interpreter to store the result of the\n last evaluation; it is stored in the "builtins" module. When not\n in interactive mode, "_" has no special meaning and is not defined.\n See section *The import statement*.\n\n Note: The name "_" is often used in conjunction with\n internationalization; refer to the documentation for the\n "gettext" module for more information on this convention.\n\n"__*__"\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of "__*__" names, in any context, that does not\n follow explicitly documented use, is subject to breakage without\n warning.\n\n"__*"\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', + 'if': '\nThe "if" statement\n******************\n\nThe "if" statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the "if" statement is executed or evaluated).\nIf all expressions are false, the suite of the "else" clause, if\npresent, is executed.\n', + 'imaginary': '\nImaginary literals\n******************\n\nImaginary literals are described by the following lexical definitions:\n\n imagnumber ::= (floatnumber | intpart) ("j" | "J")\n\nAn imaginary literal yields a complex number with a real part of 0.0.\nComplex numbers are represented as a pair of floating point numbers\nand have the same restrictions on their range. To create a complex\nnumber with a nonzero real part, add a floating point number to it,\ne.g., "(3+4j)". Some examples of imaginary literals:\n\n 3.14j 10.j 10j .001j 1e100j 3.14e-10j\n', + 'import': '\nThe "import" statement\n**********************\n\n import_stmt ::= "import" module ["as" name] ( "," module ["as" name] )*\n | "from" relative_module "import" identifier ["as" name]\n ( "," identifier ["as" name] )*\n | "from" relative_module "import" "(" identifier ["as" name]\n ( "," identifier ["as" name] )* [","] ")"\n | "from" module "import" "*"\n module ::= (identifier ".")* identifier\n relative_module ::= "."* module | "."+\n name ::= identifier\n\nThe basic import statement (no "from" clause) is executed in two\nsteps:\n\n1. find a module, loading and initializing it if necessary\n\n2. define a name or names in the local namespace for the scope\n where the "import" statement occurs.\n\nWhen the statement contains multiple clauses (separated by commas) the\ntwo steps are carried out separately for each clause, just as though\nthe clauses had been separated out into individiual import statements.\n\nThe details of the first step, finding and loading modules is\ndescribed in greater detail in the section on the *import system*,\nwhich also describes the various types of packages and modules that\ncan be imported, as well as all the hooks that can be used to\ncustomize the import system. Note that failures in this step may\nindicate either that the module could not be located, *or* that an\nerror occurred while initializing the module, which includes execution\nof the module\'s code.\n\nIf the requested module is retrieved successfully, it will be made\navailable in the local namespace in one of three ways:\n\n* If the module name is followed by "as", then the name following\n "as" is bound directly to the imported module.\n\n* If no other name is specified, and the module being imported is a\n top level module, the module\'s name is bound in the local namespace\n as a reference to the imported module\n\n* If the module being imported is *not* a top level module, then the\n name of the top level package that contains the module is bound in\n the local namespace as a reference to the top level package. The\n imported module must be accessed using its full qualified name\n rather than directly\n\nThe "from" form uses a slightly more complex process:\n\n1. find the module specified in the "from" clause loading and\n initializing it if necessary;\n\n2. for each of the identifiers specified in the "import" clauses:\n\n 1. check if the imported module has an attribute by that name\n\n 2. if not, attempt to import a submodule with that name and then\n check the imported module again for that attribute\n\n 3. if the attribute is not found, "ImportError" is raised.\n\n 4. otherwise, a reference to that value is bound in the local\n namespace, using the name in the "as" clause if it is present,\n otherwise using the attribute name\n\nExamples:\n\n import foo # foo imported and bound locally\n import foo.bar.baz # foo.bar.baz imported, foo bound locally\n import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb\n from foo.bar import baz # foo.bar.baz imported and bound as baz\n from foo import attr # foo imported and foo.attr bound as attr\n\nIf the list of identifiers is replaced by a star ("\'*\'"), all public\nnames defined in the module are bound in the local namespace for the\nscope where the "import" statement occurs.\n\nThe *public names* defined by a module are determined by checking the\nmodule\'s namespace for a variable named "__all__"; if defined, it must\nbe a sequence of strings which are names defined or imported by that\nmodule. The names given in "__all__" are all considered public and\nare required to exist. If "__all__" is not defined, the set of public\nnames includes all names found in the module\'s namespace which do not\nbegin with an underscore character ("\'_\'"). "__all__" should contain\nthe entire public API. It is intended to avoid accidentally exporting\nitems that are not part of the API (such as library modules which were\nimported and used within the module).\n\nThe "from" form with "*" may only occur in a module scope. The wild\ncard form of import --- "import *" --- is only allowed at the module\nlevel. Attempting to use it in class or function definitions will\nraise a "SyntaxError".\n\nWhen specifying what module to import you do not have to specify the\nabsolute name of the module. When a module or package is contained\nwithin another package it is possible to make a relative import within\nthe same top package without having to mention the package name. By\nusing leading dots in the specified module or package after "from" you\ncan specify how high to traverse up the current package hierarchy\nwithout specifying exact names. One leading dot means the current\npackage where the module making the import exists. Two dots means up\none package level. Three dots is up two levels, etc. So if you execute\n"from . import mod" from a module in the "pkg" package then you will\nend up importing "pkg.mod". If you execute "from ..subpkg2 import mod"\nfrom within "pkg.subpkg1" you will import "pkg.subpkg2.mod". The\nspecification for relative imports is contained within **PEP 328**.\n\n"importlib.import_module()" is provided to support applications that\ndetermine which modules need to be loaded dynamically.\n\n\nFuture statements\n=================\n\nA *future statement* is a directive to the compiler that a particular\nmodule should be compiled using syntax or semantics that will be\navailable in a specified future release of Python. The future\nstatement is intended to ease migration to future versions of Python\nthat introduce incompatible changes to the language. It allows use of\nthe new features on a per-module basis before the release in which the\nfeature becomes standard.\n\n future_statement ::= "from" "__future__" "import" feature ["as" name]\n ("," feature ["as" name])*\n | "from" "__future__" "import" "(" feature ["as" name]\n ("," feature ["as" name])* [","] ")"\n feature ::= identifier\n name ::= identifier\n\nA future statement must appear near the top of the module. The only\nlines that can appear before a future statement are:\n\n* the module docstring (if any),\n\n* comments,\n\n* blank lines, and\n\n* other future statements.\n\nThe features recognized by Python 3.0 are "absolute_import",\n"division", "generators", "unicode_literals", "print_function",\n"nested_scopes" and "with_statement". They are all redundant because\nthey are always enabled, and only kept for backwards compatibility.\n\nA future statement is recognized and treated specially at compile\ntime: Changes to the semantics of core constructs are often\nimplemented by generating different code. It may even be the case\nthat a new feature introduces new incompatible syntax (such as a new\nreserved word), in which case the compiler may need to parse the\nmodule differently. Such decisions cannot be pushed off until\nruntime.\n\nFor any given release, the compiler knows which feature names have\nbeen defined, and raises a compile-time error if a future statement\ncontains a feature not known to it.\n\nThe direct runtime semantics are the same as for any import statement:\nthere is a standard module "__future__", described later, and it will\nbe imported in the usual way at the time the future statement is\nexecuted.\n\nThe interesting runtime semantics depend on the specific feature\nenabled by the future statement.\n\nNote that there is nothing special about the statement:\n\n import __future__ [as name]\n\nThat is not a future statement; it\'s an ordinary import statement with\nno special semantics or syntax restrictions.\n\nCode compiled by calls to the built-in functions "exec()" and\n"compile()" that occur in a module "M" containing a future statement\nwill, by default, use the new syntax or semantics associated with the\nfuture statement. This can be controlled by optional arguments to\n"compile()" --- see the documentation of that function for details.\n\nA future statement typed at an interactive interpreter prompt will\ntake effect for the rest of the interpreter session. If an\ninterpreter is started with the *-i* option, is passed a script name\nto execute, and the script includes a future statement, it will be in\neffect in the interactive session started after the script is\nexecuted.\n\nSee also: **PEP 236** - Back to the __future__\n\n The original proposal for the __future__ mechanism.\n', + 'in': '\nComparisons\n***********\n\nUnlike C, all comparison operations in Python have the same priority,\nwhich is lower than that of any arithmetic, shifting or bitwise\noperation. Also unlike C, expressions like "a < b < c" have the\ninterpretation that is conventional in mathematics:\n\n comparison ::= or_expr ( comp_operator or_expr )*\n comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="\n | "is" ["not"] | ["not"] "in"\n\nComparisons yield boolean values: "True" or "False".\n\nComparisons can be chained arbitrarily, e.g., "x < y <= z" is\nequivalent to "x < y and y <= z", except that "y" is evaluated only\nonce (but in both cases "z" is not evaluated at all when "x < y" is\nfound to be false).\n\nFormally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and *op1*,\n*op2*, ..., *opN* are comparison operators, then "a op1 b op2 c ... y\nopN z" is equivalent to "a op1 b and b op2 c and ... y opN z", except\nthat each expression is evaluated at most once.\n\nNote that "a op1 b op2 c" doesn\'t imply any kind of comparison between\n*a* and *c*, so that, e.g., "x < y > z" is perfectly legal (though\nperhaps not pretty).\n\nThe operators "<", ">", "==", ">=", "<=", and "!=" compare the values\nof two objects. The objects need not have the same type. If both are\nnumbers, they are converted to a common type. Otherwise, the "==" and\n"!=" operators *always* consider objects of different types to be\nunequal, while the "<", ">", ">=" and "<=" operators raise a\n"TypeError" when comparing objects of different types that do not\nimplement these operators for the given pair of types. You can\ncontrol comparison behavior of objects of non-built-in types by\ndefining rich comparison methods like "__gt__()", described in section\n*Basic customization*.\n\nComparison of objects of the same type depends on the type:\n\n* Numbers are compared arithmetically.\n\n* The values "float(\'NaN\')" and "Decimal(\'NaN\')" are special. The\n are identical to themselves, "x is x" but are not equal to\n themselves, "x != x". Additionally, comparing any value to a\n not-a-number value will return "False". For example, both "3 <\n float(\'NaN\')" and "float(\'NaN\') < 3" will return "False".\n\n* Bytes objects are compared lexicographically using the numeric\n values of their elements.\n\n* Strings are compared lexicographically using the numeric\n equivalents (the result of the built-in function "ord()") of their\n characters. [3] String and bytes object can\'t be compared!\n\n* Tuples and lists are compared lexicographically using comparison\n of corresponding elements. This means that to compare equal, each\n element must compare equal and the two sequences must be of the same\n type and have the same length.\n\n If not equal, the sequences are ordered the same as their first\n differing elements. For example, "[1,2,x] <= [1,2,y]" has the same\n value as "x <= y". If the corresponding element does not exist, the\n shorter sequence is ordered first (for example, "[1,2] < [1,2,3]").\n\n* Mappings (dictionaries) compare equal if and only if they have the\n same "(key, value)" pairs. Order comparisons "(\'<\', \'<=\', \'>=\',\n \'>\')" raise "TypeError".\n\n* Sets and frozensets define comparison operators to mean subset and\n superset tests. Those relations do not define total orderings (the\n two sets "{1,2}" and {2,3} are not equal, nor subsets of one\n another, nor supersets of one another). Accordingly, sets are not\n appropriate arguments for functions which depend on total ordering.\n For example, "min()", "max()", and "sorted()" produce undefined\n results given a list of sets as inputs.\n\n* Most other objects of built-in types compare unequal unless they\n are the same object; the choice whether one object is considered\n smaller or larger than another one is made arbitrarily but\n consistently within one execution of a program.\n\nComparison of objects of the differing types depends on whether either\nof the types provide explicit support for the comparison. Most\nnumeric types can be compared with one another. When cross-type\ncomparison is not supported, the comparison method returns\n"NotImplemented".\n\nThe operators "in" and "not in" test for membership. "x in s"\nevaluates to true if *x* is a member of *s*, and false otherwise. "x\nnot in s" returns the negation of "x in s". All built-in sequences\nand set types support this as well as dictionary, for which "in" tests\nwhether a the dictionary has a given key. For container types such as\nlist, tuple, set, frozenset, dict, or collections.deque, the\nexpression "x in y" is equivalent to "any(x is e or x == e for e in\ny)".\n\nFor the string and bytes types, "x in y" is true if and only if *x* is\na substring of *y*. An equivalent test is "y.find(x) != -1". Empty\nstrings are always considered to be a substring of any other string,\nso """ in "abc"" will return "True".\n\nFor user-defined classes which define the "__contains__()" method, "x\nin y" is true if and only if "y.__contains__(x)" is true.\n\nFor user-defined classes which do not define "__contains__()" but do\ndefine "__iter__()", "x in y" is true if some value "z" with "x == z"\nis produced while iterating over "y". If an exception is raised\nduring the iteration, it is as if "in" raised that exception.\n\nLastly, the old-style iteration protocol is tried: if a class defines\n"__getitem__()", "x in y" is true if and only if there is a non-\nnegative integer index *i* such that "x == y[i]", and all lower\ninteger indices do not raise "IndexError" exception. (If any other\nexception is raised, it is as if "in" raised that exception).\n\nThe operator "not in" is defined to have the inverse true value of\n"in".\n\nThe operators "is" and "is not" test for object identity: "x is y" is\ntrue if and only if *x* and *y* are the same object. "x is not y"\nyields the inverse truth value. [4]\n', 'integers': '\nInteger literals\n****************\n\nInteger literals are described by the following lexical definitions:\n\n integer ::= decimalinteger | octinteger | hexinteger | bininteger\n decimalinteger ::= nonzerodigit digit* | "0"+\n nonzerodigit ::= "1"..."9"\n digit ::= "0"..."9"\n octinteger ::= "0" ("o" | "O") octdigit+\n hexinteger ::= "0" ("x" | "X") hexdigit+\n bininteger ::= "0" ("b" | "B") bindigit+\n octdigit ::= "0"..."7"\n hexdigit ::= digit | "a"..."f" | "A"..."F"\n bindigit ::= "0" | "1"\n\nThere is no limit for the length of integer literals apart from what\ncan be stored in available memory.\n\nNote that leading zeros in a non-zero decimal number are not allowed.\nThis is for disambiguation with C-style octal literals, which Python\nused before version 3.0.\n\nSome examples of integer literals:\n\n 7 2147483647 0o177 0b100110111\n 3 79228162514264337593543950336 0o377 0x100000000\n 79228162514264337593543950336 0xdeadbeef\n', - 'lambda': '\nLambdas\n*******\n\n lambda_expr ::= "lambda" [parameter_list]: expression\n lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond\n\nLambda expressions (sometimes called lambda forms) have the same\nsyntactic position as expressions. They are a shorthand to create\nanonymous functions; the expression ``lambda arguments: expression``\nyields a function object. The unnamed object behaves like a function\nobject defined with\n\n def (arguments):\n return expression\n\nSee section *Function definitions* for the syntax of parameter lists.\nNote that functions created with lambda expressions cannot contain\nstatements or annotations.\n', + 'lambda': '\nLambdas\n*******\n\n lambda_expr ::= "lambda" [parameter_list]: expression\n lambda_expr_nocond ::= "lambda" [parameter_list]: expression_nocond\n\nLambda expressions (sometimes called lambda forms) have the same\nsyntactic position as expressions. They are a shorthand to create\nanonymous functions; the expression "lambda arguments: expression"\nyields a function object. The unnamed object behaves like a function\nobject defined with\n\n def (arguments):\n return expression\n\nSee section *Function definitions* for the syntax of parameter lists.\nNote that functions created with lambda expressions cannot contain\nstatements or annotations.\n', 'lists': '\nList displays\n*************\n\nA list display is a possibly empty series of expressions enclosed in\nsquare brackets:\n\n list_display ::= "[" [expression_list | comprehension] "]"\n\nA list display yields a new list object, the contents being specified\nby either a list of expressions or a comprehension. When a comma-\nseparated list of expressions is supplied, its elements are evaluated\nfrom left to right and placed into the list object in that order.\nWhen a comprehension is supplied, the list is constructed from the\nelements resulting from the comprehension.\n', - 'naming': "\nNaming and binding\n******************\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the '**-c**' option) is a code block. The string argument passed\nto the built-in functions ``eval()`` and ``exec()`` is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block's execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block's *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as ``nonlocal``. If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a ``NameError`` exception is raised.\nIf the name refers to a local variable that has not been bound, a\n``UnboundLocalError`` exception is raised. ``UnboundLocalError`` is a\nsubclass of ``NameError``.\n\nThe following constructs bind names: formal parameters to functions,\n``import`` statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, ``for`` loop header, or\nafter ``as`` in a ``with`` statement or ``except`` clause. The\n``import`` statement of the form ``from ... import *`` binds all names\ndefined in the imported module, except those beginning with an\nunderscore. This form may only be used at the module level.\n\nA target occurring in a ``del`` statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the ``global`` statement occurs within a block, all uses of the\nname specified in the statement refer to the binding of that name in\nthe top-level namespace. Names are resolved in the top-level\nnamespace by searching the global namespace, i.e. the namespace of the\nmodule containing the code block, and the builtins namespace, the\nnamespace of the module ``builtins``. The global namespace is\nsearched first. If the name is not found there, the builtins\nnamespace is searched. The global statement must precede all uses of\nthe name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name ``__builtins__`` in its\nglobal namespace; this should be a dictionary or a module (in the\nlatter case the module's dictionary is used). By default, when in the\n``__main__`` module, ``__builtins__`` is the built-in module\n``builtins``; when in any other module, ``__builtins__`` is an alias\nfor the dictionary of the ``builtins`` module itself.\n``__builtins__`` can be set to a user-created dictionary to create a\nweak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n``__builtins__``; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should ``import``\nthe ``builtins`` module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n``__main__``.\n\nThe ``global`` statement has the same scope as a name binding\noperation in the same block. If the nearest enclosing scope for a\nfree variable contains a global statement, the free variable is\ntreated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n=================================\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- ``import *`` --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a ``SyntaxError``.\n\nThe ``eval()`` and ``exec()`` functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe ``exec()`` and ``eval()`` functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n", - 'nonlocal': '\nThe ``nonlocal`` statement\n**************************\n\n nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*\n\nThe ``nonlocal`` statement causes the listed identifiers to refer to\npreviously bound variables in the nearest enclosing scope. This is\nimportant because the default behavior for binding is to search the\nlocal namespace first. The statement allows encapsulated code to\nrebind variables outside of the local scope besides the global\n(module) scope.\n\nNames listed in a ``nonlocal`` statement, unlike to those listed in a\n``global`` statement, must refer to pre-existing bindings in an\nenclosing scope (the scope in which a new binding should be created\ncannot be determined unambiguously).\n\nNames listed in a ``nonlocal`` statement must not collide with pre-\nexisting bindings in the local scope.\n\nSee also:\n\n **PEP 3104** - Access to Names in Outer Scopes\n The specification for the ``nonlocal`` statement.\n', - 'numbers': "\nNumeric literals\n****************\n\nThere are three types of numeric literals: integers, floating point\nnumbers, and imaginary numbers. There are no complex literals\n(complex numbers can be formed by adding a real number and an\nimaginary number).\n\nNote that numeric literals do not include a sign; a phrase like ``-1``\nis actually an expression composed of the unary operator '``-``' and\nthe literal ``1``.\n", - 'numeric-types': "\nEmulating numeric types\n***********************\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations (``+``, ``-``, ``*``, ``/``, ``//``, ``%``,\n ``divmod()``, ``pow()``, ``**``, ``<<``, ``>>``, ``&``, ``^``,\n ``|``). For instance, to evaluate the expression ``x + y``, where\n *x* is an instance of a class that has an ``__add__()`` method,\n ``x.__add__(y)`` is called. The ``__divmod__()`` method should be\n the equivalent to using ``__floordiv__()`` and ``__mod__()``; it\n should not be related to ``__truediv__()``. Note that\n ``__pow__()`` should be defined to accept an optional third\n argument if the ternary version of the built-in ``pow()`` function\n is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return ``NotImplemented``.\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations (``+``, ``-``, ``*``, ``/``, ``//``, ``%``,\n ``divmod()``, ``pow()``, ``**``, ``<<``, ``>>``, ``&``, ``^``,\n ``|``) with reflected (swapped) operands. These functions are only\n called if the left operand does not support the corresponding\n operation and the operands are of different types. [2] For\n instance, to evaluate the expression ``x - y``, where *y* is an\n instance of a class that has an ``__rsub__()`` method,\n ``y.__rsub__(x)`` is called if ``x.__sub__(y)`` returns\n *NotImplemented*.\n\n Note that ternary ``pow()`` will not try calling ``__rpow__()``\n (the coercion rules would become too complicated).\n\n Note: If the right operand's type is a subclass of the left operand's\n type and that subclass provides the reflected method for the\n operation, this method will be called before the left operand's\n non-reflected method. This behavior allows subclasses to\n override their ancestors' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments (``+=``, ``-=``, ``*=``, ``/=``, ``//=``, ``%=``,\n ``**=``, ``<<=``, ``>>=``, ``&=``, ``^=``, ``|=``). These methods\n should attempt to do the operation in-place (modifying *self*) and\n return the result (which could be, but does not have to be,\n *self*). If a specific method is not defined, the augmented\n assignment falls back to the normal methods. For instance, to\n execute the statement ``x += y``, where *x* is an instance of a\n class that has an ``__iadd__()`` method, ``x.__iadd__(y)`` is\n called. If *x* is an instance of a class that does not define a\n ``__iadd__()`` method, ``x.__add__(y)`` and ``y.__radd__(x)`` are\n considered, as with the evaluation of ``x + y``.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations (``-``, ``+``,\n ``abs()`` and ``~``).\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions ``complex()``,\n ``int()``, ``float()`` and ``round()``. Should return a value of\n the appropriate type.\n\nobject.__index__(self)\n\n Called to implement ``operator.index()``. Also called whenever\n Python needs an integer object (such as in slicing, or in the\n built-in ``bin()``, ``hex()`` and ``oct()`` functions). Must return\n an integer.\n", - 'objects': '\nObjects, values and types\n*************************\n\n*Objects* are Python\'s abstraction for data. All data in a Python\nprogram is represented by objects or by relations between objects. (In\na sense, and in conformance to Von Neumann\'s model of a "stored\nprogram computer," code is also represented by objects.)\n\nEvery object has an identity, a type and a value. An object\'s\n*identity* never changes once it has been created; you may think of it\nas the object\'s address in memory. The \'``is``\' operator compares the\nidentity of two objects; the ``id()`` function returns an integer\nrepresenting its identity.\n\n**CPython implementation detail:** For CPython, ``id(x)`` is the\nmemory address where ``x`` is stored.\n\nAn object\'s type determines the operations that the object supports\n(e.g., "does it have a length?") and also defines the possible values\nfor objects of that type. The ``type()`` function returns an object\'s\ntype (which is an object itself). Like its identity, an object\'s\n*type* is also unchangeable. [1]\n\nThe *value* of some objects can change. Objects whose value can\nchange are said to be *mutable*; objects whose value is unchangeable\nonce they are created are called *immutable*. (The value of an\nimmutable container object that contains a reference to a mutable\nobject can change when the latter\'s value is changed; however the\ncontainer is still considered immutable, because the collection of\nobjects it contains cannot be changed. So, immutability is not\nstrictly the same as having an unchangeable value, it is more subtle.)\nAn object\'s mutability is determined by its type; for instance,\nnumbers, strings and tuples are immutable, while dictionaries and\nlists are mutable.\n\nObjects are never explicitly destroyed; however, when they become\nunreachable they may be garbage-collected. An implementation is\nallowed to postpone garbage collection or omit it altogether --- it is\na matter of implementation quality how garbage collection is\nimplemented, as long as no objects are collected that are still\nreachable.\n\n**CPython implementation detail:** CPython currently uses a reference-\ncounting scheme with (optional) delayed detection of cyclically linked\ngarbage, which collects most objects as soon as they become\nunreachable, but is not guaranteed to collect garbage containing\ncircular references. See the documentation of the ``gc`` module for\ninformation on controlling the collection of cyclic garbage. Other\nimplementations act differently and CPython may change. Do not depend\non immediate finalization of objects when they become unreachable (ex:\nalways close files).\n\nNote that the use of the implementation\'s tracing or debugging\nfacilities may keep objects alive that would normally be collectable.\nAlso note that catching an exception with a \'``try``...``except``\'\nstatement may keep objects alive.\n\nSome objects contain references to "external" resources such as open\nfiles or windows. It is understood that these resources are freed\nwhen the object is garbage-collected, but since garbage collection is\nnot guaranteed to happen, such objects also provide an explicit way to\nrelease the external resource, usually a ``close()`` method. Programs\nare strongly recommended to explicitly close such objects. The\n\'``try``...``finally``\' statement and the \'``with``\' statement provide\nconvenient ways to do this.\n\nSome objects contain references to other objects; these are called\n*containers*. Examples of containers are tuples, lists and\ndictionaries. The references are part of a container\'s value. In\nmost cases, when we talk about the value of a container, we imply the\nvalues, not the identities of the contained objects; however, when we\ntalk about the mutability of a container, only the identities of the\nimmediately contained objects are implied. So, if an immutable\ncontainer (like a tuple) contains a reference to a mutable object, its\nvalue changes if that mutable object is changed.\n\nTypes affect almost all aspects of object behavior. Even the\nimportance of object identity is affected in some sense: for immutable\ntypes, operations that compute new values may actually return a\nreference to any existing object with the same type and value, while\nfor mutable objects this is not allowed. E.g., after ``a = 1; b =\n1``, ``a`` and ``b`` may or may not refer to the same object with the\nvalue one, depending on the implementation, but after ``c = []; d =\n[]``, ``c`` and ``d`` are guaranteed to refer to two different,\nunique, newly created empty lists. (Note that ``c = d = []`` assigns\nthe same object to both ``c`` and ``d``.)\n', - 'operator-summary': '\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedences in Python,\nfrom lowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for comparisons, including\ntests, which all have the same precedence and chain from left to right\n--- see section *Comparisons* --- and exponentiation, which groups\nfrom right to left).\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| ``lambda`` | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| ``if`` -- ``else`` | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| ``or`` | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| ``and`` | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| ``not`` ``x`` | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| ``in``, ``not in``, ``is``, ``is not``, ``<``, | Comparisons, including membership |\n| ``<=``, ``>``, ``>=``, ``!=``, ``==`` | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| ``|`` | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| ``^`` | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| ``&`` | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| ``<<``, ``>>`` | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| ``+``, ``-`` | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| ``*``, ``/``, ``//``, ``%`` | Multiplication, division, remainder |\n| | [5] |\n+-------------------------------------------------+---------------------------------------+\n| ``+x``, ``-x``, ``~x`` | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| ``**`` | Exponentiation [6] |\n+-------------------------------------------------+---------------------------------------+\n| ``x[index]``, ``x[index:index]``, | Subscription, slicing, call, |\n| ``x(arguments...)``, ``x.attribute`` | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| ``(expressions...)``, ``[expressions...]``, | Binding or tuple display, list |\n| ``{key: value...}``, ``{expressions...}`` | display, dictionary display, set |\n| | display |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] While ``abs(x%y) < abs(y)`` is true mathematically, for floats it\n may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that ``-1e-100 % 1e100`` have the same\n sign as ``1e100``, the computed result is ``-1e-100 + 1e100``,\n which is numerically exactly equal to ``1e100``. The function\n ``math.fmod()`` returns a result whose sign matches the sign of\n the first argument instead, and so returns ``-1e-100`` in this\n case. Which approach is more appropriate depends on the\n application.\n\n[2] If x is very close to an exact integer multiple of y, it\'s\n possible for ``x//y`` to be one larger than ``(x-x%y)//y`` due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that ``divmod(x,y)[0] * y + x % y`` be very\n close to ``x``.\n\n[3] While comparisons between strings make sense at the byte level,\n they may be counter-intuitive to users. For example, the strings\n ``"\\u00C7"`` and ``"\\u0327\\u0043"`` compare differently, even\n though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using ``unicodedata.normalize()``.\n\n[4] Due to automatic garbage-collection, free lists, and the dynamic\n nature of descriptors, you may notice seemingly unusual behaviour\n in certain uses of the ``is`` operator, like those involving\n comparisons between instance methods, or constants. Check their\n documentation for more info.\n\n[5] The ``%`` operator is also used for string formatting; the same\n precedence applies.\n\n[6] The power operator ``**`` binds less tightly than an arithmetic or\n bitwise unary operator on its right, that is, ``2**-1`` is\n ``0.5``.\n', - 'pass': '\nThe ``pass`` statement\n**********************\n\n pass_stmt ::= "pass"\n\n``pass`` is a null operation --- when it is executed, nothing happens.\nIt is useful as a placeholder when a statement is required\nsyntactically, but no code needs to be executed, for example:\n\n def f(arg): pass # a function that does nothing (yet)\n\n class C: pass # a class with no methods (yet)\n', - 'power': '\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= primary ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): ``-1**2`` results in ``-1``.\n\nThe power operator has the same semantics as the built-in ``pow()``\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type, and the result is of that type.\n\nFor int operands, the result has the same type as the operands unless\nthe second argument is negative; in that case, all arguments are\nconverted to float and a float result is delivered. For example,\n``10**2`` returns ``100``, but ``10**-2`` returns ``0.01``.\n\nRaising ``0.0`` to a negative power results in a\n``ZeroDivisionError``. Raising a negative number to a fractional power\nresults in a ``complex`` number. (In earlier versions it raised a\n``ValueError``.)\n', - 'raise': '\nThe ``raise`` statement\n***********************\n\n raise_stmt ::= "raise" [expression ["from" expression]]\n\nIf no expressions are present, ``raise`` re-raises the last exception\nthat was active in the current scope. If no exception is active in\nthe current scope, a ``RuntimeError`` exception is raised indicating\nthat this is an error.\n\nOtherwise, ``raise`` evaluates the first expression as the exception\nobject. It must be either a subclass or an instance of\n``BaseException``. If it is a class, the exception instance will be\nobtained when needed by instantiating the class with no arguments.\n\nThe *type* of the exception is the exception instance\'s class, the\n*value* is the instance itself.\n\nA traceback object is normally created automatically when an exception\nis raised and attached to it as the ``__traceback__`` attribute, which\nis writable. You can create an exception and set your own traceback in\none step using the ``with_traceback()`` exception method (which\nreturns the same exception instance, with its traceback set to its\nargument), like so:\n\n raise Exception("foo occurred").with_traceback(tracebackobj)\n\nThe ``from`` clause is used for exception chaining: if given, the\nsecond *expression* must be another exception class or instance, which\nwill then be attached to the raised exception as the ``__cause__``\nattribute (which is writable). If the raised exception is not\nhandled, both exceptions will be printed:\n\n >>> try:\n ... print(1 / 0)\n ... except Exception as exc:\n ... raise RuntimeError("Something bad happened") from exc\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n The above exception was the direct cause of the following exception:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nA similar mechanism works implicitly if an exception is raised inside\nan exception handler: the previous exception is then attached as the\nnew exception\'s ``__context__`` attribute:\n\n >>> try:\n ... print(1 / 0)\n ... except:\n ... raise RuntimeError("Something bad happened")\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n During handling of the above exception, another exception occurred:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information about handling exceptions is in section\n*The try statement*.\n', - 'return': '\nThe ``return`` statement\n************************\n\n return_stmt ::= "return" [expression_list]\n\n``return`` may only occur syntactically nested in a function\ndefinition, not within a nested class definition.\n\nIf an expression list is present, it is evaluated, else ``None`` is\nsubstituted.\n\n``return`` leaves the current function call with the expression list\n(or ``None``) as return value.\n\nWhen ``return`` passes control out of a ``try`` statement with a\n``finally`` clause, that ``finally`` clause is executed before really\nleaving the function.\n\nIn a generator function, the ``return`` statement indicates that the\ngenerator is done and will cause ``StopIteration`` to be raised. The\nreturned value (if any) is used as an argument to construct\n``StopIteration`` and becomes the ``StopIteration.value`` attribute.\n', - 'sequence-types': "\nEmulating container types\n*************************\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which ``0 <= k < N``\nwhere *N* is the length of the sequence, or slice objects, which\ndefine a range of items. It is also recommended that mappings provide\nthe methods ``keys()``, ``values()``, ``items()``, ``get()``,\n``clear()``, ``setdefault()``, ``pop()``, ``popitem()``, ``copy()``,\nand ``update()`` behaving similar to those for Python's standard\ndictionary objects. The ``collections`` module provides a\n``MutableMapping`` abstract base class to help create those methods\nfrom a base set of ``__getitem__()``, ``__setitem__()``,\n``__delitem__()``, and ``keys()``. Mutable sequences should provide\nmethods ``append()``, ``count()``, ``index()``, ``extend()``,\n``insert()``, ``pop()``, ``remove()``, ``reverse()`` and ``sort()``,\nlike Python standard list objects. Finally, sequence types should\nimplement addition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods ``__add__()``, ``__radd__()``,\n``__iadd__()``, ``__mul__()``, ``__rmul__()`` and ``__imul__()``\ndescribed below; they should not define other numerical operators. It\nis recommended that both mappings and sequences implement the\n``__contains__()`` method to allow efficient use of the ``in``\noperator; for mappings, ``in`` should search the mapping's keys; for\nsequences, it should search through the values. It is further\nrecommended that both mappings and sequences implement the\n``__iter__()`` method to allow efficient iteration through the\ncontainer; for mappings, ``__iter__()`` should be the same as\n``keys()``; for sequences, it should iterate through the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function ``len()``. Should return\n the length of the object, an integer ``>=`` 0. Also, an object\n that doesn't define a ``__bool__()`` method and whose ``__len__()``\n method returns zero is considered to be false in a Boolean context.\n\nNote: Slicing is done exclusively with the following three methods. A\n call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with\n ``None``.\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of ``self[key]``. For sequence\n types, the accepted keys should be integers and slice objects.\n Note that the special interpretation of negative indexes (if the\n class wishes to emulate a sequence type) is up to the\n ``__getitem__()`` method. If *key* is of an inappropriate type,\n ``TypeError`` may be raised; if of a value outside the set of\n indexes for the sequence (after any special interpretation of\n negative values), ``IndexError`` should be raised. For mapping\n types, if *key* is missing (not in the container), ``KeyError``\n should be raised.\n\n Note: ``for`` loops expect that an ``IndexError`` will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to ``self[key]``. Same note as for\n ``__getitem__()``. This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the ``__getitem__()`` method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of ``self[key]``. Same note as for\n ``__getitem__()``. This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the ``__getitem__()``\n method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method ``keys()``.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the ``reversed()`` built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the ``__reversed__()`` method is not provided, the\n ``reversed()`` built-in will fall back to using the sequence\n protocol (``__len__()`` and ``__getitem__()``). Objects that\n support the sequence protocol should only provide\n ``__reversed__()`` if they can provide an implementation that is\n more efficient than the one provided by ``reversed()``.\n\nThe membership test operators (``in`` and ``not in``) are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don't define ``__contains__()``, the membership\n test first tries iteration via ``__iter__()``, then the old\n sequence iteration protocol via ``__getitem__()``, see *this\n section in the language reference*.\n", - 'shifting': '\nShifting operations\n*******************\n\nThe shifting operations have lower priority than the arithmetic\noperations:\n\n shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr\n\nThese operators accept integers as arguments. They shift the first\nargument to the left or right by the number of bits given by the\nsecond argument.\n\nA right shift by *n* bits is defined as floor division by\n``pow(2,n)``. A left shift by *n* bits is defined as multiplication\nwith ``pow(2,n)``.\n\nNote: In the current implementation, the right-hand operand is required to\n be at most ``sys.maxsize``. If the right-hand operand is larger\n than ``sys.maxsize`` an ``OverflowError`` exception is raised.\n', - 'slicings': '\nSlicings\n********\n\nA slicing selects a range of items in a sequence object (e.g., a\nstring, tuple or list). Slicings may be used as expressions or as\ntargets in assignment or ``del`` statements. The syntax for a\nslicing:\n\n slicing ::= primary "[" slice_list "]"\n slice_list ::= slice_item ("," slice_item)* [","]\n slice_item ::= expression | proper_slice\n proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]\n lower_bound ::= expression\n upper_bound ::= expression\n stride ::= expression\n\nThere is ambiguity in the formal syntax here: anything that looks like\nan expression list also looks like a slice list, so any subscription\ncan be interpreted as a slicing. Rather than further complicating the\nsyntax, this is disambiguated by defining that in this case the\ninterpretation as a subscription takes priority over the\ninterpretation as a slicing (this is the case if the slice list\ncontains no proper slice).\n\nThe semantics for a slicing are as follows. The primary must evaluate\nto a mapping object, and it is indexed (using the same\n``__getitem__()`` method as normal subscription) with a key that is\nconstructed from the slice list, as follows. If the slice list\ncontains at least one comma, the key is a tuple containing the\nconversion of the slice items; otherwise, the conversion of the lone\nslice item is the key. The conversion of a slice item that is an\nexpression is that expression. The conversion of a proper slice is a\nslice object (see section *The standard type hierarchy*) whose\n``start``, ``stop`` and ``step`` attributes are the values of the\nexpressions given as lower bound, upper bound and stride,\nrespectively, substituting ``None`` for missing expressions.\n', - 'specialattrs': '\nSpecial Attributes\n******************\n\nThe implementation adds a few special read-only attributes to several\nobject types, where they are relevant. Some of these are not reported\nby the ``dir()`` built-in function.\n\nobject.__dict__\n\n A dictionary or other mapping object used to store an object\'s\n (writable) attributes.\n\ninstance.__class__\n\n The class to which a class instance belongs.\n\nclass.__bases__\n\n The tuple of base classes of a class object.\n\nclass.__name__\n\n The name of the class or type.\n\nclass.__qualname__\n\n The *qualified name* of the class or type.\n\n New in version 3.3.\n\nclass.__mro__\n\n This attribute is a tuple of classes that are considered when\n looking for base classes during method resolution.\n\nclass.mro()\n\n This method can be overridden by a metaclass to customize the\n method resolution order for its instances. It is called at class\n instantiation, and its result is stored in ``__mro__``.\n\nclass.__subclasses__()\n\n Each class keeps a list of weak references to its immediate\n subclasses. This method returns a list of all those references\n still alive. Example:\n\n >>> int.__subclasses__()\n []\n\n-[ Footnotes ]-\n\n[1] Additional information on these special methods may be found in\n the Python Reference Manual (*Basic customization*).\n\n[2] As a consequence, the list ``[1, 2]`` is considered equal to\n ``[1.0, 2.0]``, and similarly for tuples.\n\n[3] They must have since the parser can\'t tell the type of the\n operands.\n\n[4] Cased characters are those with general category property being\n one of "Lu" (Letter, uppercase), "Ll" (Letter, lowercase), or "Lt"\n (Letter, titlecase).\n\n[5] To format only a tuple you should therefore provide a singleton\n tuple whose only element is the tuple to be formatted.\n', - 'specialnames': '\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named ``__getitem__()``, and ``x`` is an instance of this\nclass, then ``x[i]`` is roughly equivalent to ``type(x).__getitem__(x,\ni)``. Except where mentioned, attempts to execute an operation raise\nan exception when no appropriate method is defined (typically\n``AttributeError`` or ``TypeError``).\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n``NodeList`` interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. ``__new__()`` is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of ``__new__()`` should be the new object instance (usually\n an instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s ``__new__()`` method using\n ``super(currentclass, cls).__new__(cls[, ...])`` with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If ``__new__()`` returns an instance of *cls*, then the new\n instance\'s ``__init__()`` method will be invoked like\n ``__init__(self[, ...])``, where *self* is the new instance and the\n remaining arguments are the same as were passed to ``__new__()``.\n\n If ``__new__()`` does not return an instance of *cls*, then the new\n instance\'s ``__init__()`` method will not be invoked.\n\n ``__new__()`` is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called when the instance is created. The arguments are those\n passed to the class constructor expression. If a base class has an\n ``__init__()`` method, the derived class\'s ``__init__()`` method,\n if any, must explicitly call it to ensure proper initialization of\n the base class part of the instance; for example:\n ``BaseClass.__init__(self, [args...])``. As a special constraint\n on constructors, no value may be returned; doing so will cause a\n ``TypeError`` to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a ``__del__()`` method,\n the derived class\'s ``__del__()`` method, if any, must explicitly\n call it to ensure proper deletion of the base class part of the\n instance. Note that it is possible (though not recommended!) for\n the ``__del__()`` method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n ``__del__()`` methods are called for objects that still exist when\n the interpreter exits.\n\n Note: ``del x`` doesn\'t directly call ``x.__del__()`` --- the former\n decrements the reference count for ``x`` by one, and the latter\n is only called when ``x``\'s reference count reaches zero. Some\n common situations that may prevent the reference count of an\n object from going to zero include: circular references between\n objects (e.g., a doubly-linked list or a tree data structure with\n parent and child pointers); a reference to the object on the\n stack frame of a function that caught an exception (the traceback\n stored in ``sys.exc_info()[2]`` keeps the stack frame alive); or\n a reference to the object on the stack frame that raised an\n unhandled exception in interactive mode (the traceback stored in\n ``sys.last_traceback`` keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing ``None`` in\n ``sys.last_traceback``. Circular references which are garbage are\n detected when the option cycle detector is enabled (it\'s on by\n default), but can only be cleaned up if there are no Python-\n level ``__del__()`` methods involved. Refer to the documentation\n for the ``gc`` module for more information about how\n ``__del__()`` methods are handled by the cycle detector,\n particularly the description of the ``garbage`` value.\n\n Warning: Due to the precarious circumstances under which ``__del__()``\n methods are invoked, exceptions that occur during their execution\n are ignored, and a warning is printed to ``sys.stderr`` instead.\n Also, when ``__del__()`` is invoked in response to a module being\n deleted (e.g., when execution of the program is done), other\n globals referenced by the ``__del__()`` method may already have\n been deleted or in the process of being torn down (e.g. the\n import machinery shutting down). For this reason, ``__del__()``\n methods should do the absolute minimum needed to maintain\n external invariants. Starting with version 1.5, Python\n guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the ``__del__()`` method is called.\n\nobject.__repr__(self)\n\n Called by the ``repr()`` built-in function to compute the\n "official" string representation of an object. If at all possible,\n this should look like a valid Python expression that could be used\n to recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n ``<...some useful description...>`` should be returned. The return\n value must be a string object. If a class defines ``__repr__()``\n but not ``__str__()``, then ``__repr__()`` is also used when an\n "informal" string representation of instances of that class is\n required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by ``str(object)`` and the built-in functions ``format()``\n and ``print()`` to compute the "informal" or nicely printable\n string representation of an object. The return value must be a\n *string* object.\n\n This method differs from ``object.__repr__()`` in that there is no\n expectation that ``__str__()`` return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type ``object``\n calls ``object.__repr__()``.\n\nobject.__bytes__(self)\n\n Called by ``bytes()`` to compute a byte-string representation of an\n object. This should return a ``bytes`` object.\n\nobject.__format__(self, format_spec)\n\n Called by the ``format()`` built-in function (and by extension, the\n ``str.format()`` method of class ``str``) to produce a "formatted"\n string representation of an object. The ``format_spec`` argument is\n a string that contains a description of the formatting options\n desired. The interpretation of the ``format_spec`` argument is up\n to the type implementing ``__format__()``, however most classes\n will either delegate formatting to one of the built-in types, or\n use a similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: ``xy`` calls ``x.__gt__(y)``, and ``x>=y`` calls\n ``x.__ge__(y)``.\n\n A rich comparison method may return the singleton\n ``NotImplemented`` if it does not implement the operation for a\n given pair of arguments. By convention, ``False`` and ``True`` are\n returned for a successful comparison. However, these methods can\n return any value, so if the comparison operator is used in a\n Boolean context (e.g., in the condition of an ``if`` statement),\n Python will call ``bool()`` on the value to determine if the result\n is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of ``x==y`` does not imply that ``x!=y`` is false.\n Accordingly, when defining ``__eq__()``, one should also define\n ``__ne__()`` so that the operators will behave as expected. See\n the paragraph on ``__hash__()`` for some important notes on\n creating *hashable* objects which support custom comparison\n operations and are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, ``__lt__()`` and ``__gt__()`` are each\n other\'s reflection, ``__le__()`` and ``__ge__()`` are each other\'s\n reflection, and ``__eq__()`` and ``__ne__()`` are their own\n reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see ``functools.total_ordering()``.\n\nobject.__hash__(self)\n\n Called by built-in function ``hash()`` and for operations on\n members of hashed collections including ``set``, ``frozenset``, and\n ``dict``. ``__hash__()`` should return an integer. The only\n required property is that objects which compare equal have the same\n hash value; it is advised to somehow mix together (e.g. using\n exclusive or) the hash values for the components of the object that\n also play a part in comparison of objects.\n\n Note: ``hash()`` truncates the value returned from an object\'s custom\n ``__hash__()`` method to the size of a ``Py_ssize_t``. This is\n typically 8 bytes on 64-bit builds and 4 bytes on 32-bit builds.\n If an object\'s ``__hash__()`` must interoperate on builds of\n different bit sizes, be sure to check the width on all supported\n builds. An easy way to do this is with ``python -c "import sys;\n print(sys.hash_info.width)"``\n\n If a class does not define an ``__eq__()`` method it should not\n define a ``__hash__()`` operation either; if it defines\n ``__eq__()`` but not ``__hash__()``, its instances will not be\n usable as items in hashable collections. If a class defines\n mutable objects and implements an ``__eq__()`` method, it should\n not implement ``__hash__()``, since the implementation of hashable\n collections requires that a key\'s hash value is immutable (if the\n object\'s hash value changes, it will be in the wrong hash bucket).\n\n User-defined classes have ``__eq__()`` and ``__hash__()`` methods\n by default; with them, all objects compare unequal (except with\n themselves) and ``x.__hash__()`` returns an appropriate value such\n that ``x == y`` implies both that ``x is y`` and ``hash(x) ==\n hash(y)``.\n\n A class that overrides ``__eq__()`` and does not define\n ``__hash__()`` will have its ``__hash__()`` implicitly set to\n ``None``. When the ``__hash__()`` method of a class is ``None``,\n instances of the class will raise an appropriate ``TypeError`` when\n a program attempts to retrieve their hash value, and will also be\n correctly identified as unhashable when checking ``isinstance(obj,\n collections.Hashable``).\n\n If a class that overrides ``__eq__()`` needs to retain the\n implementation of ``__hash__()`` from a parent class, the\n interpreter must be told this explicitly by setting ``__hash__ =\n .__hash__``.\n\n If a class that does not override ``__eq__()`` wishes to suppress\n hash support, it should include ``__hash__ = None`` in the class\n definition. A class which defines its own ``__hash__()`` that\n explicitly raises a ``TypeError`` would be incorrectly identified\n as hashable by an ``isinstance(obj, collections.Hashable)`` call.\n\n Note: By default, the ``__hash__()`` values of str, bytes and datetime\n objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also ``PYTHONHASHSEED``.\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n ``bool()``; should return ``False`` or ``True``. When this method\n is not defined, ``__len__()`` is called, if it is defined, and the\n object is considered true if its result is nonzero. If a class\n defines neither ``__len__()`` nor ``__bool__()``, all its instances\n are considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of ``x.name``)\nfor class instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for ``self``). ``name`` is the attribute name.\n This method should return the (computed) attribute value or raise\n an ``AttributeError`` exception.\n\n Note that if the attribute is found through the normal mechanism,\n ``__getattr__()`` is not called. (This is an intentional asymmetry\n between ``__getattr__()`` and ``__setattr__()``.) This is done both\n for efficiency reasons and because otherwise ``__getattr__()``\n would have no way to access other attributes of the instance. Note\n that at least for instance variables, you can fake total control by\n not inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n ``__getattribute__()`` method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines\n ``__getattr__()``, the latter will not be called unless\n ``__getattribute__()`` either calls it explicitly or raises an\n ``AttributeError``. This method should return the (computed)\n attribute value or raise an ``AttributeError`` exception. In order\n to avoid infinite recursion in this method, its implementation\n should always call the base class method with the same name to\n access any attributes it needs, for example,\n ``object.__getattribute__(self, name)``.\n\n Note: This method may still be bypassed when looking up special methods\n as the result of implicit invocation via language syntax or\n built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If ``__setattr__()`` wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n ``object.__setattr__(self, name, value)``.\n\nobject.__delattr__(self, name)\n\n Like ``__setattr__()`` but for attribute deletion instead of\n assignment. This should only be implemented if ``del obj.name`` is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when ``dir()`` is called on the object. A sequence must be\n returned. ``dir()`` converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' ``__dict__``.\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or ``None`` when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an\n ``AttributeError`` exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: ``__get__()``, ``__set__()``, and\n``__delete__()``. If any of those methods are defined for an object,\nit is said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, ``a.x`` has a\nlookup chain starting with ``a.__dict__[\'x\']``, then\n``type(a).__dict__[\'x\']``, and continuing through the base classes of\n``type(a)`` excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, ``a.x``.\nHow the arguments are assembled depends on ``a``:\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: ``x.__get__(a)``.\n\nInstance Binding\n If binding to an object instance, ``a.x`` is transformed into the\n call: ``type(a).__dict__[\'x\'].__get__(a, type(a))``.\n\nClass Binding\n If binding to a class, ``A.x`` is transformed into the call:\n ``A.__dict__[\'x\'].__get__(None, A)``.\n\nSuper Binding\n If ``a`` is an instance of ``super``, then the binding ``super(B,\n obj).m()`` searches ``obj.__class__.__mro__`` for the base class\n ``A`` immediately preceding ``B`` and then invokes the descriptor\n with the call: ``A.__dict__[\'m\'].__get__(obj, obj.__class__)``.\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of ``__get__()``, ``__set__()`` and ``__delete__()``.\nIf it does not define ``__get__()``, then accessing the attribute will\nreturn the descriptor object itself unless there is a value in the\nobject\'s instance dictionary. If the descriptor defines ``__set__()``\nand/or ``__delete__()``, it is a data descriptor; if it defines\nneither, it is a non-data descriptor. Normally, data descriptors\ndefine both ``__get__()`` and ``__set__()``, while non-data\ndescriptors have just the ``__get__()`` method. Data descriptors with\n``__set__()`` and ``__get__()`` defined always override a redefinition\nin an instance dictionary. In contrast, non-data descriptors can be\noverridden by instances.\n\nPython methods (including ``staticmethod()`` and ``classmethod()``)\nare implemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe ``property()`` function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n class, *__slots__* reserves space for the declared variables and\n prevents the automatic creation of *__dict__* and *__weakref__* for\n each instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises ``AttributeError``. If\n dynamic assignment of new variables is desired, then add\n ``\'__dict__\'`` to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes defining\n *__slots__* do not support weak references to its instances. If weak\n reference support is needed, then add ``\'__weakref__\'`` to the\n sequence of strings in the *__slots__* declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the instance\n variable defined by the base class slot is inaccessible (except by\n retrieving its descriptor directly from the base class). This\n renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as ``int``, ``str`` and\n ``tuple``.\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings may\n also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using ``type()``. The class body\nis executed in a new namespace and the class name is bound locally to\nthe result of ``type(name, bases, namespace)``.\n\nThe class creation process can be customised by passing the\n``metaclass`` keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both ``MyClass`` and ``MySubclass`` are\ninstances of ``Meta``:\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then ``type()`` is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n ``type()``, then it is used directly as the metaclass\n\n* if an instance of ``type()`` is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. ``type(cls)``) of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with ``TypeError``.\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a ``__prepare__``\nattribute, it is called as ``namespace = metaclass.__prepare__(name,\nbases, **kwds)`` (where the additional keyword arguments, if any, come\nfrom the class definition).\n\nIf the metaclass has no ``__prepare__`` attribute, then the class\nnamespace is initialised as an empty ``dict()`` instance.\n\nSee also:\n\n **PEP 3115** - Metaclasses in Python 3000\n Introduced the ``__prepare__`` namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as ``exec(body, globals(),\nnamespace)``. The key difference from a normal call to ``exec()`` is\nthat lexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling ``metaclass(name, bases,\nnamespace, **kwds)`` (the additional keywords passed here are the same\nas those passed to ``__prepare__``).\n\nThis class object is the one that will be referenced by the zero-\nargument form of ``super()``. ``__class__`` is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either ``__class__`` or ``super``. This allows the zero argument\nform of ``super()`` to correctly identify the class being defined\nbased on lexical scoping, while the class or instance that was used to\nmake the current call is identified based on the first argument passed\nto the method.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also:\n\n **PEP 3135** - New super\n Describes the implicit ``__class__`` closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n``collections.OrderedDict`` to remember the order that class members\nwere defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s ``__prepare__()`` method which returns an\nempty ``collections.OrderedDict``. That mapping records the methods\nand attributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s ``__new__()`` method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called ``members``.\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n``isinstance()`` and ``issubclass()`` built-in functions.\n\nIn particular, the metaclass ``abc.ABCMeta`` implements these methods\nin order to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n ``isinstance(instance, class)``.\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n ``issubclass(subclass, class)``.\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also:\n\n **PEP 3119** - Introducing Abstract Base Classes\n Includes the specification for customizing ``isinstance()`` and\n ``issubclass()`` behavior through ``__instancecheck__()`` and\n ``__subclasscheck__()``, with motivation for this functionality\n in the context of adding Abstract Base Classes (see the ``abc``\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, ``x(arg1, arg2, ...)`` is a shorthand for\n ``x.__call__(arg1, arg2, ...)``.\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which ``0 <= k < N``\nwhere *N* is the length of the sequence, or slice objects, which\ndefine a range of items. It is also recommended that mappings provide\nthe methods ``keys()``, ``values()``, ``items()``, ``get()``,\n``clear()``, ``setdefault()``, ``pop()``, ``popitem()``, ``copy()``,\nand ``update()`` behaving similar to those for Python\'s standard\ndictionary objects. The ``collections`` module provides a\n``MutableMapping`` abstract base class to help create those methods\nfrom a base set of ``__getitem__()``, ``__setitem__()``,\n``__delitem__()``, and ``keys()``. Mutable sequences should provide\nmethods ``append()``, ``count()``, ``index()``, ``extend()``,\n``insert()``, ``pop()``, ``remove()``, ``reverse()`` and ``sort()``,\nlike Python standard list objects. Finally, sequence types should\nimplement addition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods ``__add__()``, ``__radd__()``,\n``__iadd__()``, ``__mul__()``, ``__rmul__()`` and ``__imul__()``\ndescribed below; they should not define other numerical operators. It\nis recommended that both mappings and sequences implement the\n``__contains__()`` method to allow efficient use of the ``in``\noperator; for mappings, ``in`` should search the mapping\'s keys; for\nsequences, it should search through the values. It is further\nrecommended that both mappings and sequences implement the\n``__iter__()`` method to allow efficient iteration through the\ncontainer; for mappings, ``__iter__()`` should be the same as\n``keys()``; for sequences, it should iterate through the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function ``len()``. Should return\n the length of the object, an integer ``>=`` 0. Also, an object\n that doesn\'t define a ``__bool__()`` method and whose ``__len__()``\n method returns zero is considered to be false in a Boolean context.\n\nNote: Slicing is done exclusively with the following three methods. A\n call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with\n ``None``.\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of ``self[key]``. For sequence\n types, the accepted keys should be integers and slice objects.\n Note that the special interpretation of negative indexes (if the\n class wishes to emulate a sequence type) is up to the\n ``__getitem__()`` method. If *key* is of an inappropriate type,\n ``TypeError`` may be raised; if of a value outside the set of\n indexes for the sequence (after any special interpretation of\n negative values), ``IndexError`` should be raised. For mapping\n types, if *key* is missing (not in the container), ``KeyError``\n should be raised.\n\n Note: ``for`` loops expect that an ``IndexError`` will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to ``self[key]``. Same note as for\n ``__getitem__()``. This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the ``__getitem__()`` method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of ``self[key]``. Same note as for\n ``__getitem__()``. This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the ``__getitem__()``\n method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method ``keys()``.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the ``reversed()`` built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the ``__reversed__()`` method is not provided, the\n ``reversed()`` built-in will fall back to using the sequence\n protocol (``__len__()`` and ``__getitem__()``). Objects that\n support the sequence protocol should only provide\n ``__reversed__()`` if they can provide an implementation that is\n more efficient than the one provided by ``reversed()``.\n\nThe membership test operators (``in`` and ``not in``) are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define ``__contains__()``, the membership\n test first tries iteration via ``__iter__()``, then the old\n sequence iteration protocol via ``__getitem__()``, see *this\n section in the language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations (``+``, ``-``, ``*``, ``/``, ``//``, ``%``,\n ``divmod()``, ``pow()``, ``**``, ``<<``, ``>>``, ``&``, ``^``,\n ``|``). For instance, to evaluate the expression ``x + y``, where\n *x* is an instance of a class that has an ``__add__()`` method,\n ``x.__add__(y)`` is called. The ``__divmod__()`` method should be\n the equivalent to using ``__floordiv__()`` and ``__mod__()``; it\n should not be related to ``__truediv__()``. Note that\n ``__pow__()`` should be defined to accept an optional third\n argument if the ternary version of the built-in ``pow()`` function\n is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return ``NotImplemented``.\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations (``+``, ``-``, ``*``, ``/``, ``//``, ``%``,\n ``divmod()``, ``pow()``, ``**``, ``<<``, ``>>``, ``&``, ``^``,\n ``|``) with reflected (swapped) operands. These functions are only\n called if the left operand does not support the corresponding\n operation and the operands are of different types. [2] For\n instance, to evaluate the expression ``x - y``, where *y* is an\n instance of a class that has an ``__rsub__()`` method,\n ``y.__rsub__(x)`` is called if ``x.__sub__(y)`` returns\n *NotImplemented*.\n\n Note that ternary ``pow()`` will not try calling ``__rpow__()``\n (the coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left operand\'s\n type and that subclass provides the reflected method for the\n operation, this method will be called before the left operand\'s\n non-reflected method. This behavior allows subclasses to\n override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments (``+=``, ``-=``, ``*=``, ``/=``, ``//=``, ``%=``,\n ``**=``, ``<<=``, ``>>=``, ``&=``, ``^=``, ``|=``). These methods\n should attempt to do the operation in-place (modifying *self*) and\n return the result (which could be, but does not have to be,\n *self*). If a specific method is not defined, the augmented\n assignment falls back to the normal methods. For instance, to\n execute the statement ``x += y``, where *x* is an instance of a\n class that has an ``__iadd__()`` method, ``x.__iadd__(y)`` is\n called. If *x* is an instance of a class that does not define a\n ``__iadd__()`` method, ``x.__add__(y)`` and ``y.__radd__(x)`` are\n considered, as with the evaluation of ``x + y``.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations (``-``, ``+``,\n ``abs()`` and ``~``).\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions ``complex()``,\n ``int()``, ``float()`` and ``round()``. Should return a value of\n the appropriate type.\n\nobject.__index__(self)\n\n Called to implement ``operator.index()``. Also called whenever\n Python needs an integer object (such as in slicing, or in the\n built-in ``bin()``, ``hex()`` and ``oct()`` functions). Must return\n an integer.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a ``with`` statement. The context\nmanager handles the entry into, and the exit from, the desired runtime\ncontext for the execution of the block of code. Context managers are\nnormally invoked using the ``with`` statement (described in section\n*The with statement*), but can also be used by directly invoking their\nmethods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The ``with``\n statement will bind this method\'s return value to the target(s)\n specified in the ``as`` clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be ``None``.\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that ``__exit__()`` methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as ``__hash__()`` and ``__repr__()`` that are implemented\nby all objects, including type objects. If the implicit lookup of\nthese methods used the conventional lookup process, they would fail\nwhen invoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe ``__getattribute__()`` method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the ``__getattribute__()`` machinery in this fashion\nprovides significant scope for speed optimisations within the\ninterpreter, at the cost of some flexibility in the handling of\nspecial methods (the special method *must* be set on the class object\nitself in order to be consistently invoked by the interpreter).\n\n-[ Footnotes ]-\n\n[1] It *is* possible in some cases to change an object\'s type, under\n certain controlled conditions. It generally isn\'t a good idea\n though, since it can lead to some very strange behaviour if it is\n handled incorrectly.\n\n[2] For operands of the same type, it is assumed that if the non-\n reflected method (such as ``__add__()``) fails the operation is\n not supported, which is why the reflected method is not called.\n', - 'string-methods': '\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see ``str.format()``,\n*Format String Syntax* and *String Formatting*) and the other based on\nC ``printf`` style formatting that handles a narrower range of types\nand is slightly harder to use correctly, but is often faster for the\ncases it can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the ``re`` module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter ``\'\xc3\x9f\'`` is equivalent to\n ``"ss"``. Since it is already lowercase, ``lower()`` would do\n nothing to ``\'\xc3\x9f\'``; ``casefold()`` converts it to ``"ss"``.\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is a space).\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is ``\'utf-8\'``. *errors* may be given to set a different\n error handling scheme. The default for *errors* is ``\'strict\'``,\n meaning that encoding errors raise a ``UnicodeError``. Other\n possible values are ``\'ignore\'``, ``\'replace\'``,\n ``\'xmlcharrefreplace\'``, ``\'backslashreplace\'`` and any other name\n registered via ``codecs.register_error()``, see section *Codec Base\n Classes*. For a list of possible encodings, see section *Standard\n Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return ``True`` if the string ends with the specified *suffix*,\n otherwise return ``False``. *suffix* can also be a tuple of\n suffixes to look for. With optional *start*, test beginning at\n that position. With optional *end*, stop comparing at that\n position.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab (``\\t``), one or more space characters are inserted in the\n result until the current column is equal to the next tab position.\n (The tab character itself is not copied.) If the character is a\n newline (``\\n``) or return (``\\r``), it is copied and the current\n column is reset to zero. Any other character is copied unchanged\n and the current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice ``s[start:end]``.\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return ``-1`` if *sub* is not found.\n\n Note: The ``find()`` method should be used only if you need to know the\n position of *sub*. To check if *sub* is a substring or not, use\n the ``in`` operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces ``{}``. Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to ``str.format(**mapping)``, except that ``mapping`` is\n used directly and not copied to a ``dict`` . This is useful if for\n example ``mapping`` is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like ``find()``, but raise ``ValueError`` when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character\n ``c`` is alphanumeric if one of the following returns ``True``:\n ``c.isalpha()``, ``c.isdecimal()``, ``c.isdigit()``, or\n ``c.isnumeric()``.\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use ``keyword.iskeyword()`` to test for reserved identifiers such\n as ``def`` and ``class``.\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when ``repr()`` is\n invoked on a string. It has no bearing on the handling of strings\n written to ``sys.stdout`` or ``sys.stderr``.)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A ``TypeError`` will be raised if there are\n any non-string values in *iterable*, including ``bytes`` objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to ``len(s)``.\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or ``None``, the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n ``str.translate()``.\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within ``s[start:end]``.\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return ``-1`` on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like ``rfind()`` but raises ``ValueError`` when the substring *sub*\n is not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to ``len(s)``.\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n ``None``, any whitespace string is a separator. Except for\n splitting from the right, ``rsplit()`` behaves like ``split()``\n which is described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or ``None``, the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most ``maxsplit+1``\n elements). If *maxsplit* is not specified or ``-1``, then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n ``\'1,,2\'.split(\',\')`` returns ``[\'1\', \'\', \'2\']``). The *sep*\n argument may consist of multiple characters (for example,\n ``\'1<>2<>3\'.split(\'<>\')`` returns ``[\'1\', \'2\', \'3\']``). Splitting\n an empty string with a specified separator returns ``[\'\']``.\n\n If *sep* is not specified or is ``None``, a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a ``None`` separator returns\n ``[]``.\n\n For example, ``\' 1 2 3 \'.split()`` returns ``[\'1\', \'2\', \'3\']``,\n and ``\' 1 2 3 \'.split(None, 1)`` returns ``[\'1\', \'2 3 \']``.\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example, ``\'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()`` returns\n ``[\'ab c\', \'\', \'de fg\', \'kl\']``, while the same call with\n ``splitlines(True)`` returns ``[\'ab c\\n\', \'\\n\', \'de fg\\r\',\n \'kl\\r\\n\']``.\n\n Unlike ``split()`` when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line.\n\nstr.startswith(prefix[, start[, end]])\n\n Return ``True`` if string starts with the *prefix*, otherwise\n return ``False``. *prefix* can also be a tuple of prefixes to look\n for. With optional *start*, test string beginning at that\n position. With optional *end*, stop comparing string at that\n position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or ``None``, the\n *chars* argument defaults to removing whitespace. The *chars*\n argument is not a prefix or suffix; rather, all combinations of its\n values are stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n ``s.swapcase().swapcase() == s``.\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(map)\n\n Return a copy of the *s* where all characters have been mapped\n through the *map* which must be a dictionary of Unicode ordinals\n (integers) to Unicode ordinals, strings or ``None``. Unmapped\n characters are left untouched. Characters mapped to ``None`` are\n deleted.\n\n You can use ``str.maketrans()`` to create a translation map from\n character-to-character mappings in different formats.\n\n Note: An even more flexible approach is to create a custom character\n mapping codec using the ``codecs`` module (see\n ``encodings.cp1251`` for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that ``str.upper().isupper()`` might\n be ``False`` if ``s`` contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to ``len(s)``.\n', - 'strings': '\nString and Bytes literals\n*************************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "R" | "U"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'" | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | stringescapeseq\n longstringitem ::= longstringchar | stringescapeseq\n shortstringchar ::= \n longstringchar ::= \n stringescapeseq ::= "\\" \n\n bytesliteral ::= bytesprefix(shortbytes | longbytes)\n bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"\n shortbytes ::= "\'" shortbytesitem* "\'" | \'"\' shortbytesitem* \'"\'\n longbytes ::= "\'\'\'" longbytesitem* "\'\'\'" | \'"""\' longbytesitem* \'"""\'\n shortbytesitem ::= shortbyteschar | bytesescapeseq\n longbytesitem ::= longbyteschar | bytesescapeseq\n shortbyteschar ::= \n longbyteschar ::= \n bytesescapeseq ::= "\\" \n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the ``stringprefix`` or\n``bytesprefix`` and the rest of the literal. The source character set\nis defined by the encoding declaration; it is UTF-8 if no encoding\ndeclaration is given in the source file; see section *Encoding\ndeclarations*.\n\nIn plain English: Both types of literals can be enclosed in matching\nsingle quotes (``\'``) or double quotes (``"``). They can also be\nenclosed in matching groups of three single or double quotes (these\nare generally referred to as *triple-quoted strings*). The backslash\n(``\\``) character is used to escape characters that otherwise have a\nspecial meaning, such as newline, backslash itself, or the quote\ncharacter.\n\nBytes literals are always prefixed with ``\'b\'`` or ``\'B\'``; they\nproduce an instance of the ``bytes`` type instead of the ``str`` type.\nThey may only contain ASCII characters; bytes with a numeric value of\n128 or greater must be expressed with escapes.\n\nAs of Python 3.3 it is possible again to prefix unicode strings with a\n``u`` prefix to simplify maintenance of dual 2.x and 3.x codebases.\n\nBoth string and bytes literals may optionally be prefixed with a\nletter ``\'r\'`` or ``\'R\'``; such strings are called *raw strings* and\ntreat backslashes as literal characters. As a result, in string\nliterals, ``\'\\U\'`` and ``\'\\u\'`` escapes in raw strings are not treated\nspecially. Given that Python 2.x\'s raw unicode literals behave\ndifferently than Python 3.x\'s the ``\'ur\'`` syntax is not supported.\n\n New in version 3.3: The ``\'rb\'`` prefix of raw bytes literals has\n been added as a synonym of ``\'br\'``.\n\n New in version 3.3: Support for the unicode legacy literal\n (``u\'value\'``) was reintroduced to simplify the maintenance of dual\n Python 2.x and 3.x codebases. See **PEP 414** for more information.\n\nIn triple-quoted strings, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the string. (A "quote" is the character used to open the\nstring, i.e. either ``\'`` or ``"``.)\n\nUnless an ``\'r\'`` or ``\'R\'`` prefix is present, escape sequences in\nstrings are interpreted according to rules similar to those used by\nStandard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| ``\\newline`` | Backslash and newline ignored | |\n+-------------------+-----------------------------------+---------+\n| ``\\\\`` | Backslash (``\\``) | |\n+-------------------+-----------------------------------+---------+\n| ``\\\'`` | Single quote (``\'``) | |\n+-------------------+-----------------------------------+---------+\n| ``\\"`` | Double quote (``"``) | |\n+-------------------+-----------------------------------+---------+\n| ``\\a`` | ASCII Bell (BEL) | |\n+-------------------+-----------------------------------+---------+\n| ``\\b`` | ASCII Backspace (BS) | |\n+-------------------+-----------------------------------+---------+\n| ``\\f`` | ASCII Formfeed (FF) | |\n+-------------------+-----------------------------------+---------+\n| ``\\n`` | ASCII Linefeed (LF) | |\n+-------------------+-----------------------------------+---------+\n| ``\\r`` | ASCII Carriage Return (CR) | |\n+-------------------+-----------------------------------+---------+\n| ``\\t`` | ASCII Horizontal Tab (TAB) | |\n+-------------------+-----------------------------------+---------+\n| ``\\v`` | ASCII Vertical Tab (VT) | |\n+-------------------+-----------------------------------+---------+\n| ``\\ooo`` | Character with octal value *ooo* | (1,3) |\n+-------------------+-----------------------------------+---------+\n| ``\\xhh`` | Character with hex value *hh* | (2,3) |\n+-------------------+-----------------------------------+---------+\n\nEscape sequences only recognized in string literals are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| ``\\N{name}`` | Character named *name* in the | (4) |\n| | Unicode database | |\n+-------------------+-----------------------------------+---------+\n| ``\\uxxxx`` | Character with 16-bit hex value | (5) |\n| | *xxxx* | |\n+-------------------+-----------------------------------+---------+\n| ``\\Uxxxxxxxx`` | Character with 32-bit hex value | (6) |\n| | *xxxxxxxx* | |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. As in Standard C, up to three octal digits are accepted.\n\n2. Unlike in Standard C, exactly two hex digits are required.\n\n3. In a bytes literal, hexadecimal and octal escapes denote the byte\n with the given value. In a string literal, these escapes denote a\n Unicode character with the given value.\n\n4. Changed in version 3.3: Support for name aliases [1] has been\n added.\n\n5. Individual code units which form parts of a surrogate pair can be\n encoded using this escape sequence. Exactly four hex digits are\n required.\n\n6. Any Unicode character can be encoded this way. Exactly eight hex\n digits are required.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the string*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences only recognized in string\nliterals fall into the category of unrecognized escapes for bytes\nliterals.\n\nEven in a raw string, string quotes can be escaped with a backslash,\nbut the backslash remains in the string; for example, ``r"\\""`` is a\nvalid string literal consisting of two characters: a backslash and a\ndouble quote; ``r"\\"`` is not a valid string literal (even a raw\nstring cannot end in an odd number of backslashes). Specifically, *a\nraw string cannot end in a single backslash* (since the backslash\nwould escape the following quote character). Note also that a single\nbackslash followed by a newline is interpreted as those two characters\nas part of the string, *not* as a line continuation.\n', - 'subscriptions': '\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object that supports subscription,\ne.g. a list or dictionary. User-defined objects can support\nsubscription by defining a ``__getitem__()`` method.\n\nFor built-in objects, there are two types of objects that support\nsubscription:\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to\nan integer or a slice (as discussed in the following section).\n\nThe formal syntax makes no special provision for negative indices in\nsequences; however, built-in sequences all provide a ``__getitem__()``\nmethod that interprets negative indices by adding the length of the\nsequence to the index (so that ``x[-1]`` selects the last item of\n``x``). The resulting value must be a nonnegative integer less than\nthe number of items in the sequence, and the subscription selects the\nitem whose index is that value (counting from zero). Since the support\nfor negative indices and slicing occurs in the object\'s\n``__getitem__()`` method, subclasses overriding this method will need\nto explicitly add that support.\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n', - 'truth': "\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an ``if`` or\n``while`` condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* ``None``\n\n* ``False``\n\n* zero of any numeric type, for example, ``0``, ``0.0``, ``0j``.\n\n* any empty sequence, for example, ``''``, ``()``, ``[]``.\n\n* any empty mapping, for example, ``{}``.\n\n* instances of user-defined classes, if the class defines a\n ``__bool__()`` or ``__len__()`` method, when that method returns the\n integer zero or ``bool`` value ``False``. [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn ``0`` or ``False`` for false and ``1`` or ``True`` for true,\nunless otherwise stated. (Important exception: the Boolean operations\n``or`` and ``and`` always return one of their operands.)\n", - 'try': '\nThe ``try`` statement\n*********************\n\nThe ``try`` statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" target]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe ``except`` clause(s) specify one or more exception handlers. When\nno exception occurs in the ``try`` clause, no exception handler is\nexecuted. When an exception occurs in the ``try`` suite, a search for\nan exception handler is started. This search inspects the except\nclauses in turn until one is found that matches the exception. An\nexpression-less except clause, if present, must be last; it matches\nany exception. For an except clause with an expression, that\nexpression is evaluated, and the clause matches the exception if the\nresulting object is "compatible" with the exception. An object is\ncompatible with an exception if it is the class or a base class of the\nexception object or a tuple containing an item compatible with the\nexception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire ``try`` statement\nraised the exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the ``as`` keyword in that except clause,\nif present, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using ``as target``, it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the ``sys`` module and can be access via\n``sys.exc_info()``. ``sys.exc_info()`` returns a 3-tuple consisting of\nthe exception class, the exception instance and a traceback object\n(see section *The standard type hierarchy*) identifying the point in\nthe program where the exception occurred. ``sys.exc_info()`` values\nare restored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional ``else`` clause is executed if and when control flows off\nthe end of the ``try`` clause. [2] Exceptions in the ``else`` clause\nare not handled by the preceding ``except`` clauses.\n\nIf ``finally`` is present, it specifies a \'cleanup\' handler. The\n``try`` clause is executed, including any ``except`` and ``else``\nclauses. If an exception occurs in any of the clauses and is not\nhandled, the exception is temporarily saved. The ``finally`` clause is\nexecuted. If there is a saved exception it is re-raised at the end of\nthe ``finally`` clause. If the ``finally`` clause raises another\nexception, the saved exception is set as the context of the new\nexception. If the ``finally`` clause executes a ``return`` or\n``break`` statement, the saved exception is discarded:\n\n def f():\n try:\n 1/0\n finally:\n return 42\n\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the ``finally`` clause.\n\nWhen a ``return``, ``break`` or ``continue`` statement is executed in\nthe ``try`` suite of a ``try``...``finally`` statement, the\n``finally`` clause is also executed \'on the way out.\' A ``continue``\nstatement is illegal in the ``finally`` clause. (The reason is a\nproblem with the current implementation --- this restriction may be\nlifted in the future).\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the ``raise`` statement to\ngenerate exceptions may be found in section *The raise statement*.\n', - 'types': '\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.), although such additions\nwill often be provided via the standard library instead.\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name ``None``.\n It is used to signify the absence of a value in many situations,\n e.g., it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n ``NotImplemented``. Numeric methods and rich comparison methods may\n return this value if they do not implement the operation for the\n operands provided. (The interpreter will then try the reflected\n operation, or some other fallback, depending on the operator.) Its\n truth value is true.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the literal ``...`` or the\n built-in name ``Ellipsis``. Its truth value is true.\n\n``numbers.Number``\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n ``numbers.Integral``\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are two types of integers:\n\n Integers (``int``)\n\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans (``bool``)\n These represent the truth values False and True. The two\n objects representing the values False and True are the only\n Boolean objects. The Boolean type is a subtype of the integer\n type, and Boolean values behave like the values 0 and 1,\n respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ``"False"`` or\n ``"True"`` are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers.\n\n ``numbers.Real`` (``float``)\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these is\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n ``numbers.Complex`` (``complex``)\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number ``z`` can be retrieved through the read-only\n attributes ``z.real`` and ``z.imag``.\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function ``len()`` returns the number of\n items of a sequence. When the length of a sequence is *n*, the\n index set contains the numbers 0, 1, ..., *n*-1. Item *i* of\n sequence *a* is selected by ``a[i]``.\n\n Sequences also support slicing: ``a[i:j]`` selects all items with\n index *k* such that *i* ``<=`` *k* ``<`` *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: ``a[i:j:k]`` selects all items of *a* with index *x*\n where ``x = i + n*k``, *n* ``>=`` ``0`` and *i* ``<=`` *x* ``<``\n *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n A string is a sequence of values that represent Unicode\n codepoints. All the codepoints in range ``U+0000 - U+10FFFF``\n can be represented in a string. Python doesn\'t have a\n ``chr`` type, and every character in the string is\n represented as a string object with length ``1``. The built-\n in function ``ord()`` converts a character to its codepoint\n (as an integer); ``chr()`` converts an integer in range ``0 -\n 10FFFF`` to the corresponding character. ``str.encode()`` can\n be used to convert a ``str`` to ``bytes`` using the given\n encoding, and ``bytes.decode()`` can be used to achieve the\n opposite.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Bytes\n A bytes object is an immutable array. The items are 8-bit\n bytes, represented by integers in the range 0 <= x < 256.\n Bytes literals (like ``b\'abc\'``) and the built-in function\n ``bytes()`` can be used to construct bytes objects. Also,\n bytes objects can be decoded to strings via the ``decode()``\n method.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and ``del`` (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in ``bytearray()`` constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module ``array`` provides an additional example of\n a mutable sequence type, as does the ``collections`` module.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function ``len()``\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., ``1`` and\n ``1.0``), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n ``set()`` constructor and can be modified afterwards by several\n methods, such as ``add()``.\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in ``frozenset()`` constructor. As a frozenset is\n immutable and *hashable*, it can be used again as an element of\n another set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation ``a[k]`` selects the item indexed by\n ``k`` from the mapping ``a``; this can be used in expressions and\n as the target of assignments or ``del`` statements. The built-in\n function ``len()`` returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., ``1`` and\n ``1.0``) then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the ``{...}``\n notation (see section *Dictionary displays*).\n\n The extension modules ``dbm.ndbm`` and ``dbm.gnu`` provide\n additional examples of mapping types, as does the\n ``collections`` module.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +---------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +===========================+=================================+=============+\n | ``__doc__`` | The function\'s documentation | Writable |\n | | string, or ``None`` if | |\n | | unavailable | |\n +---------------------------+---------------------------------+-------------+\n | ``__name__`` | The function\'s name | Writable |\n +---------------------------+---------------------------------+-------------+\n | ``__qualname__`` | The function\'s *qualified name* | Writable |\n | | New in version 3.3. | |\n +---------------------------+---------------------------------+-------------+\n | ``__module__`` | The name of the module the | Writable |\n | | function was defined in, or | |\n | | ``None`` if unavailable. | |\n +---------------------------+---------------------------------+-------------+\n | ``__defaults__`` | A tuple containing default | Writable |\n | | argument values for those | |\n | | arguments that have defaults, | |\n | | or ``None`` if no arguments | |\n | | have a default value | |\n +---------------------------+---------------------------------+-------------+\n | ``__code__`` | The code object representing | Writable |\n | | the compiled function body. | |\n +---------------------------+---------------------------------+-------------+\n | ``__globals__`` | A reference to the dictionary | Read-only |\n | | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +---------------------------+---------------------------------+-------------+\n | ``__dict__`` | The namespace supporting | Writable |\n | | arbitrary function attributes. | |\n +---------------------------+---------------------------------+-------------+\n | ``__closure__`` | ``None`` or a tuple of cells | Read-only |\n | | that contain bindings for the | |\n | | function\'s free variables. | |\n +---------------------------+---------------------------------+-------------+\n | ``__annotations__`` | A dict containing annotations | Writable |\n | | of parameters. The keys of the | |\n | | dict are the parameter names, | |\n | | or ``\'return\'`` for the return | |\n | | annotation, if provided. | |\n +---------------------------+---------------------------------+-------------+\n | ``__kwdefaults__`` | A dict containing defaults for | Writable |\n | | keyword-only parameters. | |\n +---------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n Instance methods\n An instance method object combines a class, a class instance and\n any callable object (normally a user-defined function).\n\n Special read-only attributes: ``__self__`` is the class instance\n object, ``__func__`` is the function object; ``__doc__`` is the\n method\'s documentation (same as ``__func__.__doc__``);\n ``__name__`` is the method name (same as ``__func__.__name__``);\n ``__module__`` is the name of the module the method was defined\n in, or ``None`` if unavailable.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object or a class\n method object.\n\n When an instance method object is created by retrieving a user-\n defined function object from a class via one of its instances,\n its ``__self__`` attribute is the instance, and the method\n object is said to be bound. The new method\'s ``__func__``\n attribute is the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the ``__func__``\n attribute of the new instance is not the original method object\n but its ``__func__`` attribute.\n\n When an instance method object is created by retrieving a class\n method object from a class or instance, its ``__self__``\n attribute is the class itself, and its ``__func__`` attribute is\n the function object underlying the class method.\n\n When an instance method object is called, the underlying\n function (``__func__``) is called, inserting the class instance\n (``__self__``) in front of the argument list. For instance,\n when ``C`` is a class which contains a definition for a function\n ``f()``, and ``x`` is an instance of ``C``, calling ``x.f(1)``\n is equivalent to calling ``C.f(x, 1)``.\n\n When an instance method object is derived from a class method\n object, the "class instance" stored in ``__self__`` will\n actually be the class itself, so that calling either ``x.f(1)``\n or ``C.f(1)`` is equivalent to calling ``f(C,1)`` where ``f`` is\n the underlying function.\n\n Note that the transformation from function object to instance\n method object happens each time the attribute is retrieved from\n the instance. In some cases, a fruitful optimization is to\n assign the attribute to a local variable and call that local\n variable. Also notice that this transformation only happens for\n user-defined functions; other callable objects (and all non-\n callable objects) are retrieved without transformation. It is\n also important to note that user-defined functions which are\n attributes of a class instance are not converted to bound\n methods; this *only* happens when the function is an attribute\n of the class.\n\n Generator functions\n A function or method which uses the ``yield`` statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s ``iterator.__next__()`` method will cause the\n function to execute until it provides a value using the\n ``yield`` statement. When the function executes a ``return``\n statement or falls off the end, a ``StopIteration`` exception is\n raised and the iterator will have reached the end of the set of\n values to be returned.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are ``len()`` and ``math.sin()``\n (``math`` is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: ``__doc__`` is the function\'s documentation\n string, or ``None`` if unavailable; ``__name__`` is the\n function\'s name; ``__self__`` is set to ``None`` (but see the\n next item); ``__module__`` is the name of the module the\n function was defined in or ``None`` if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n ``alist.append()``, assuming *alist* is a list object. In this\n case, the special read-only attribute ``__self__`` is set to the\n object denoted by *alist*.\n\n Classes\n Classes are callable. These objects normally act as factories\n for new instances of themselves, but variations are possible for\n class types that override ``__new__()``. The arguments of the\n call are passed to ``__new__()`` and, in the typical case, to\n ``__init__()`` to initialize the new instance.\n\n Class Instances\n Instances of arbitrary classes can be made callable by defining\n a ``__call__()`` method in their class.\n\nModules\n Modules are a basic organizational unit of Python code, and are\n created by the *import system* as invoked either by the ``import``\n statement (see ``import``), or by calling functions such as\n ``importlib.import_module()`` and built-in ``__import__()``. A\n module object has a namespace implemented by a dictionary object\n (this is the dictionary referenced by the ``__globals__`` attribute\n of functions defined in the module). Attribute references are\n translated to lookups in this dictionary, e.g., ``m.x`` is\n equivalent to ``m.__dict__["x"]``. A module object does not contain\n the code object used to initialize the module (since it isn\'t\n needed once the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., ``m.x = 1`` is equivalent to ``m.__dict__["x"] = 1``.\n\n Special read-only attribute: ``__dict__`` is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: ``__name__`` is the module\'s\n name; ``__doc__`` is the module\'s documentation string, or ``None``\n if unavailable; ``__file__`` is the pathname of the file from which\n the module was loaded, if it was loaded from a file. The\n ``__file__`` attribute may be missing for certain types of modules,\n such as C modules that are statically linked into the interpreter;\n for extension modules loaded dynamically from a shared library, it\n is the pathname of the shared library file.\n\nCustom classes\n Custom class types are typically created by class definitions (see\n section *Class definitions*). A class has a namespace implemented\n by a dictionary object. Class attribute references are translated\n to lookups in this dictionary, e.g., ``C.x`` is translated to\n ``C.__dict__["x"]`` (although there are a number of hooks which\n allow for other means of locating attributes). When the attribute\n name is not found there, the attribute search continues in the base\n classes. This search of the base classes uses the C3 method\n resolution order which behaves correctly even in the presence of\n \'diamond\' inheritance structures where there are multiple\n inheritance paths leading back to a common ancestor. Additional\n details on the C3 MRO used by Python can be found in the\n documentation accompanying the 2.3 release at\n http://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class ``C``, say) would yield\n a class method object, it is transformed into an instance method\n object whose ``__self__`` attributes is ``C``. When it would yield\n a static method object, it is transformed into the object wrapped\n by the static method object. See section *Implementing Descriptors*\n for another way in which attributes retrieved from a class may\n differ from those actually contained in its ``__dict__``.\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: ``__name__`` is the class name; ``__module__``\n is the module name in which the class was defined; ``__dict__`` is\n the dictionary containing the class\'s namespace; ``__bases__`` is a\n tuple (possibly empty or a singleton) containing the base classes,\n in the order of their occurrence in the base class list;\n ``__doc__`` is the class\'s documentation string, or None if\n undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object, it is transformed into an instance method object\n whose ``__self__`` attribute is the instance. Static method and\n class method objects are also transformed; see above under\n "Classes". See section *Implementing Descriptors* for another way\n in which attributes of a class retrieved via its instances may\n differ from the objects actually stored in the class\'s\n ``__dict__``. If no class attribute is found, and the object\'s\n class has a ``__getattr__()`` method, that is called to satisfy the\n lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n ``__setattr__()`` or ``__delattr__()`` method, this is called\n instead of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: ``__dict__`` is the attribute dictionary;\n ``__class__`` is the instance\'s class.\n\nI/O objects (also known as file objects)\n A *file object* represents an open file. Various shortcuts are\n available to create file objects: the ``open()`` built-in function,\n and also ``os.popen()``, ``os.fdopen()``, and the ``makefile()``\n method of socket objects (and perhaps by other functions or methods\n provided by extension modules).\n\n The objects ``sys.stdin``, ``sys.stdout`` and ``sys.stderr`` are\n initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams; they are all open in text\n mode and therefore follow the interface defined by the\n ``io.TextIOBase`` abstract class.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: ``co_name`` gives the function\n name; ``co_argcount`` is the number of positional arguments\n (including arguments with default values); ``co_nlocals`` is the\n number of local variables used by the function (including\n arguments); ``co_varnames`` is a tuple containing the names of\n the local variables (starting with the argument names);\n ``co_cellvars`` is a tuple containing the names of local\n variables that are referenced by nested functions;\n ``co_freevars`` is a tuple containing the names of free\n variables; ``co_code`` is a string representing the sequence of\n bytecode instructions; ``co_consts`` is a tuple containing the\n literals used by the bytecode; ``co_names`` is a tuple\n containing the names used by the bytecode; ``co_filename`` is\n the filename from which the code was compiled;\n ``co_firstlineno`` is the first line number of the function;\n ``co_lnotab`` is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); ``co_stacksize`` is the required stack size\n (including local variables); ``co_flags`` is an integer encoding\n a number of flags for the interpreter.\n\n The following flag bits are defined for ``co_flags``: bit\n ``0x04`` is set if the function uses the ``*arguments`` syntax\n to accept an arbitrary number of positional arguments; bit\n ``0x08`` is set if the function uses the ``**keywords`` syntax\n to accept arbitrary keyword arguments; bit ``0x20`` is set if\n the function is a generator.\n\n Future feature declarations (``from __future__ import\n division``) also use bits in ``co_flags`` to indicate whether a\n code object was compiled with a particular feature enabled: bit\n ``0x2000`` is set if the function was compiled with future\n division enabled; bits ``0x10`` and ``0x1000`` were used in\n earlier versions of Python.\n\n Other bits in ``co_flags`` are reserved for internal use.\n\n If a code object represents a function, the first item in\n ``co_consts`` is the documentation string of the function, or\n ``None`` if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: ``f_back`` is to the previous\n stack frame (towards the caller), or ``None`` if this is the\n bottom stack frame; ``f_code`` is the code object being executed\n in this frame; ``f_locals`` is the dictionary used to look up\n local variables; ``f_globals`` is used for global variables;\n ``f_builtins`` is used for built-in (intrinsic) names;\n ``f_lasti`` gives the precise instruction (this is an index into\n the bytecode string of the code object).\n\n Special writable attributes: ``f_trace``, if not ``None``, is a\n function called at the start of each source code line (this is\n used by the debugger); ``f_lineno`` is the current line number\n of the frame --- writing to this from within a trace function\n jumps to the given line (only for the bottom-most frame). A\n debugger can implement a Jump command (aka Set Next Statement)\n by writing to f_lineno.\n\n Traceback objects\n Traceback objects represent a stack trace of an exception. A\n traceback object is created when an exception occurs. When the\n search for an exception handler unwinds the execution stack, at\n each unwound level a traceback object is inserted in front of\n the current traceback. When an exception handler is entered,\n the stack trace is made available to the program. (See section\n *The try statement*.) It is accessible as the third item of the\n tuple returned by ``sys.exc_info()``. When the program contains\n no suitable handler, the stack trace is written (nicely\n formatted) to the standard error stream; if the interpreter is\n interactive, it is also made available to the user as\n ``sys.last_traceback``.\n\n Special read-only attributes: ``tb_next`` is the next level in\n the stack trace (towards the frame where the exception\n occurred), or ``None`` if there is no next level; ``tb_frame``\n points to the execution frame of the current level;\n ``tb_lineno`` gives the line number where the exception\n occurred; ``tb_lasti`` indicates the precise instruction. The\n line number and last instruction in the traceback may differ\n from the line number of its frame object if the exception\n occurred in a ``try`` statement with no matching except clause\n or with a finally clause.\n\n Slice objects\n Slice objects are used to represent slices for ``__getitem__()``\n methods. They are also created by the built-in ``slice()``\n function.\n\n Special read-only attributes: ``start`` is the lower bound;\n ``stop`` is the upper bound; ``step`` is the step value; each is\n ``None`` if omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the slice that the slice object\n would describe if applied to a sequence of *length* items.\n It returns a tuple of three integers; respectively these are\n the *start* and *stop* indices and the *step* or stride\n length of the slice. Missing or out-of-bounds indices are\n handled in a manner consistent with regular slices.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n ``staticmethod()`` constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in ``classmethod()`` constructor.\n', - 'typesfunctions': '\nFunctions\n*********\n\nFunction objects are created by function definitions. The only\noperation on a function object is to call it: ``func(argument-list)``.\n\nThere are really two flavors of function objects: built-in functions\nand user-defined functions. Both support the same operation (to call\nthe function), but the implementation is different, hence the\ndifferent object types.\n\nSee *Function definitions* for more information.\n', - 'typesmapping': '\nMapping Types --- ``dict``\n**************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built-\nin ``list``, ``set``, and ``tuple`` classes, and the ``collections``\nmodule.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as ``1`` and ``1.0``) then they can be used interchangeably to\nindex the same dictionary entry. (Note however, that since computers\nstore floating-point numbers as approximations it is usually unwise to\nuse them as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of\n``key: value`` pairs within braces, for example: ``{\'jack\': 4098,\n\'sjoerd\': 4127}`` or ``{4098: \'jack\', 4127: \'sjoerd\'}``, or by the\n``dict`` constructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterator*\n object. Each item in the iterable must itself be an iterator with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to ``{"one": 1, "two": 2, "three": 3}``:\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a ``KeyError`` if\n *key* is not in the map.\n\n If a subclass of dict defines a method ``__missing__()``, if the\n key *key* is not present, the ``d[key]`` operation calls that\n method with the key *key* as argument. The ``d[key]`` operation\n then returns or raises whatever is returned or raised by the\n ``__missing__(key)`` call if the key is not present. No other\n operations or methods invoke ``__missing__()``. If\n ``__missing__()`` is not defined, ``KeyError`` is raised.\n ``__missing__()`` must be a method; it cannot be an instance\n variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n See ``collections.Counter`` for a complete implementation\n including other methods helpful for accumulating and managing\n tallies.\n\n d[key] = value\n\n Set ``d[key]`` to *value*.\n\n del d[key]\n\n Remove ``d[key]`` from *d*. Raises a ``KeyError`` if *key* is\n not in the map.\n\n key in d\n\n Return ``True`` if *d* has a key *key*, else ``False``.\n\n key not in d\n\n Equivalent to ``not key in d``.\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for ``iter(d.keys())``.\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n classmethod fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n ``fromkeys()`` is a class method that returns a new dictionary.\n *value* defaults to ``None``.\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to ``None``,\n so that this method never raises a ``KeyError``.\n\n items()\n\n Return a new view of the dictionary\'s items (``(key, value)``\n pairs). See the *documentation of view objects*.\n\n keys()\n\n Return a new view of the dictionary\'s keys. See the\n *documentation of view objects*.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a ``KeyError`` is raised.\n\n popitem()\n\n Remove and return an arbitrary ``(key, value)`` pair from the\n dictionary.\n\n ``popitem()`` is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling ``popitem()`` raises a ``KeyError``.\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to ``None``.\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return ``None``.\n\n ``update()`` accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: ``d.update(red=1,\n blue=2)``.\n\n values()\n\n Return a new view of the dictionary\'s values. See the\n *documentation of view objects*.\n\nSee also:\n\n ``types.MappingProxyType`` can be used to create a read-only view\n of a ``dict``.\n\n\nDictionary view objects\n=======================\n\nThe objects returned by ``dict.keys()``, ``dict.values()`` and\n``dict.items()`` are *view objects*. They provide a dynamic view on\nthe dictionary\'s entries, which means that when the dictionary\nchanges, the view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of ``(key, value)``) in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of ``(value, key)`` pairs\n using ``zip()``: ``pairs = zip(d.values(), d.keys())``. Another\n way to create the same list is ``pairs = [(v, k) for (k, v) in\n d.items()]``.\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a ``RuntimeError`` or fail to iterate over all entries.\n\nx in dictview\n\n Return ``True`` if *x* is in the underlying dictionary\'s keys,\n values or items (in the latter case, *x* should be a ``(key,\n value)`` tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that ``(key, value)`` pairs are unique\nand hashable, then the items view is also set-like. (Values views are\nnot treated as set-like since the entries are generally not unique.)\nFor set-like views, all of the operations defined for the abstract\nbase class ``collections.abc.Set`` are available (for example, ``==``,\n``<``, or ``^``).\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.keys()\n >>> values = dishes.values()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n >>> keys ^ {\'sausage\', \'juice\'}\n {\'juice\', \'sausage\', \'bacon\', \'spam\'}\n', - 'typesmethods': '\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as ``append()`` on\nlists) and class instance methods. Built-in methods are described\nwith the types that support them.\n\nIf you access a method (a function defined in a class namespace)\nthrough an instance, you get a special object: a *bound method* (also\ncalled *instance method*) object. When called, it will add the\n``self`` argument to the argument list. Bound methods have two\nspecial read-only attributes: ``m.__self__`` is the object on which\nthe method operates, and ``m.__func__`` is the function implementing\nthe method. Calling ``m(arg-1, arg-2, ..., arg-n)`` is completely\nequivalent to calling ``m.__func__(m.__self__, arg-1, arg-2, ...,\narg-n)``.\n\nLike function objects, bound method objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object (``meth.__func__``), setting method\nattributes on bound methods is disallowed. Attempting to set an\nattribute on a method results in an ``AttributeError`` being raised.\nIn order to set a method attribute, you need to explicitly set it on\nthe underlying function object:\n\n >>> class C:\n ... def method(self):\n ... pass\n ...\n >>> c = C()\n >>> c.method.whoami = \'my name is method\' # can\'t set on the method\n Traceback (most recent call last):\n File "", line 1, in \n AttributeError: \'method\' object has no attribute \'whoami\'\n >>> c.method.__func__.whoami = \'my name is method\'\n >>> c.method.whoami\n \'my name is method\'\n\nSee *The standard type hierarchy* for more information.\n', - 'typesmodules': "\nModules\n*******\n\nThe only special operation on a module is attribute access:\n``m.name``, where *m* is a module and *name* accesses a name defined\nin *m*'s symbol table. Module attributes can be assigned to. (Note\nthat the ``import`` statement is not, strictly speaking, an operation\non a module object; ``import foo`` does not require a module object\nnamed *foo* to exist, rather it requires an (external) *definition*\nfor a module named *foo* somewhere.)\n\nA special attribute of every module is ``__dict__``. This is the\ndictionary containing the module's symbol table. Modifying this\ndictionary will actually change the module's symbol table, but direct\nassignment to the ``__dict__`` attribute is not possible (you can\nwrite ``m.__dict__['a'] = 1``, which defines ``m.a`` to be ``1``, but\nyou can't write ``m.__dict__ = {}``). Modifying ``__dict__`` directly\nis not recommended.\n\nModules built into the interpreter are written like this: ````. If loaded from a file, they are written as\n````.\n", - 'typesseq': '\nSequence Types --- ``list``, ``tuple``, ``range``\n*************************************************\n\nThere are three basic sequence types: lists, tuples, and range\nobjects. Additional sequence types tailored for processing of *binary\ndata* and *text strings* are described in dedicated sections.\n\n\nCommon Sequence Operations\n==========================\n\nThe operations in the following table are supported by most sequence\ntypes, both mutable and immutable. The ``collections.abc.Sequence``\nABC is provided to make it easier to correctly implement these\noperations on custom sequence types.\n\nThis table lists the sequence operations sorted in ascending priority\n(operations in the same box have the same priority). In the table,\n*s* and *t* are sequences of the same type, *n*, *i*, *j* and *k* are\nintegers and *x* is an arbitrary object that meets any type and value\nrestrictions imposed by *s*.\n\nThe ``in`` and ``not in`` operations have the same priorities as the\ncomparison operations. The ``+`` (concatenation) and ``*``\n(repetition) operations have the same priority as the corresponding\nnumeric operations.\n\n+----------------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+============================+==================================+============+\n| ``x in s`` | ``True`` if an item of *s* is | (1) |\n| | equal to *x*, else ``False`` | |\n+----------------------------+----------------------------------+------------+\n| ``x not in s`` | ``False`` if an item of *s* is | (1) |\n| | equal to *x*, else ``True`` | |\n+----------------------------+----------------------------------+------------+\n| ``s + t`` | the concatenation of *s* and *t* | (6)(7) |\n+----------------------------+----------------------------------+------------+\n| ``s * n`` or ``n * s`` | *n* shallow copies of *s* | (2)(7) |\n| | concatenated | |\n+----------------------------+----------------------------------+------------+\n| ``s[i]`` | *i*th item of *s*, origin 0 | (3) |\n+----------------------------+----------------------------------+------------+\n| ``s[i:j]`` | slice of *s* from *i* to *j* | (3)(4) |\n+----------------------------+----------------------------------+------------+\n| ``s[i:j:k]`` | slice of *s* from *i* to *j* | (3)(5) |\n| | with step *k* | |\n+----------------------------+----------------------------------+------------+\n| ``len(s)`` | length of *s* | |\n+----------------------------+----------------------------------+------------+\n| ``min(s)`` | smallest item of *s* | |\n+----------------------------+----------------------------------+------------+\n| ``max(s)`` | largest item of *s* | |\n+----------------------------+----------------------------------+------------+\n| ``s.index(x[, i[, j]])`` | index of the first occurrence of | (8) |\n| | *x* in *s* (at or after index | |\n| | *i* and before index *j*) | |\n+----------------------------+----------------------------------+------------+\n| ``s.count(x)`` | total number of occurrences of | |\n| | *x* in *s* | |\n+----------------------------+----------------------------------+------------+\n\nSequences of the same type also support comparisons. In particular,\ntuples and lists are compared lexicographically by comparing\ncorresponding elements. This means that to compare equal, every\nelement must compare equal and the two sequences must be of the same\ntype and have the same length. (For full details see *Comparisons* in\nthe language reference.)\n\nNotes:\n\n1. While the ``in`` and ``not in`` operations are used only for simple\n containment testing in the general case, some specialised sequences\n (such as ``str``, ``bytes`` and ``bytearray``) also use them for\n subsequence testing:\n\n >>> "gg" in "eggs"\n True\n\n2. Values of *n* less than ``0`` are treated as ``0`` (which yields an\n empty sequence of the same type as *s*). Note also that the copies\n are shallow; nested structures are not copied. This often haunts\n new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that ``[[]]`` is a one-element list containing\n an empty list, so all three elements of ``[[]] * 3`` are (pointers\n to) this single empty list. Modifying any of the elements of\n ``lists`` modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n3. If *i* or *j* is negative, the index is relative to the end of the\n string: ``len(s) + i`` or ``len(s) + j`` is substituted. But note\n that ``-0`` is still ``0``.\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that ``i <= k < j``. If *i* or *j* is\n greater than ``len(s)``, use ``len(s)``. If *i* is omitted or\n ``None``, use ``0``. If *j* is omitted or ``None``, use\n ``len(s)``. If *i* is greater than or equal to *j*, the slice is\n empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index ``x = i + n*k`` such that ``0 <= n <\n (j-i)/k``. In other words, the indices are ``i``, ``i+k``,\n ``i+2*k``, ``i+3*k`` and so on, stopping when *j* is reached (but\n never including *j*). If *i* or *j* is greater than ``len(s)``,\n use ``len(s)``. If *i* or *j* are omitted or ``None``, they become\n "end" values (which end depends on the sign of *k*). Note, *k*\n cannot be zero. If *k* is ``None``, it is treated like ``1``.\n\n6. Concatenating immutable sequences always results in a new object.\n This means that building up a sequence by repeated concatenation\n will have a quadratic runtime cost in the total sequence length.\n To get a linear runtime cost, you must switch to one of the\n alternatives below:\n\n * if concatenating ``str`` objects, you can build a list and use\n ``str.join()`` at the end or else write to a ``io.StringIO``\n instance and retrieve its value when complete\n\n * if concatenating ``bytes`` objects, you can similarly use\n ``bytes.join()`` or ``io.BytesIO``, or you can do in-place\n concatenation with a ``bytearray`` object. ``bytearray`` objects\n are mutable and have an efficient overallocation mechanism\n\n * if concatenating ``tuple`` objects, extend a ``list`` instead\n\n * for other types, investigate the relevant class documentation\n\n7. Some sequence types (such as ``range``) only support item sequences\n that follow specific patterns, and hence don\'t support sequence\n concatenation or repetition.\n\n8. ``index`` raises ``ValueError`` when *x* is not found in *s*. When\n supported, the additional arguments to the index method allow\n efficient searching of subsections of the sequence. Passing the\n extra arguments is roughly equivalent to using ``s[i:j].index(x)``,\n only without copying any data and with the returned index being\n relative to the start of the sequence rather than the start of the\n slice.\n\n\nImmutable Sequence Types\n========================\n\nThe only operation that immutable sequence types generally implement\nthat is not also implemented by mutable sequence types is support for\nthe ``hash()`` built-in.\n\nThis support allows immutable sequences, such as ``tuple`` instances,\nto be used as ``dict`` keys and stored in ``set`` and ``frozenset``\ninstances.\n\nAttempting to hash an immutable sequence that contains unhashable\nvalues will result in ``TypeError``.\n\n\nMutable Sequence Types\n======================\n\nThe operations in the following table are defined on mutable sequence\ntypes. The ``collections.abc.MutableSequence`` ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, ``bytearray`` only\naccepts integers that meet the value restriction ``0 <= x <= 255``).\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | appends *x* to the end of the | |\n| | sequence (same as | |\n| | ``s[len(s):len(s)] = [x]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.clear()`` | removes all items from ``s`` | (5) |\n| | (same as ``del s[:]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.copy()`` | creates a shallow copy of ``s`` | (5) |\n| | (same as ``s[:]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(t)`` | extends *s* with the contents of | |\n| | *t* (same as ``s[len(s):len(s)] | |\n| | = t``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | inserts *x* into *s* at the | |\n| | index given by *i* (same as | |\n| | ``s[i:i] = [x]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | retrieves the item at *i* and | (2) |\n| | also removes it from *s* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | remove the first item from *s* | (3) |\n| | where ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (4) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to ``-1``, so that by default\n the last item is removed and returned.\n\n3. ``remove`` raises ``ValueError`` when *x* is not found in *s*.\n\n4. The ``reverse()`` method modifies the sequence in place for economy\n of space when reversing a large sequence. To remind users that it\n operates by side effect, it does not return the reversed sequence.\n\n5. ``clear()`` and ``copy()`` are included for consistency with the\n interfaces of mutable containers that don\'t support slicing\n operations (such as ``dict`` and ``set``)\n\n New in version 3.3: ``clear()`` and ``copy()`` methods.\n\n\nLists\n=====\n\nLists are mutable sequences, typically used to store collections of\nhomogeneous items (where the precise degree of similarity will vary by\napplication).\n\nclass class list([iterable])\n\n Lists may be constructed in several ways:\n\n * Using a pair of square brackets to denote the empty list: ``[]``\n\n * Using square brackets, separating items with commas: ``[a]``,\n ``[a, b, c]``\n\n * Using a list comprehension: ``[x for x in iterable]``\n\n * Using the type constructor: ``list()`` or ``list(iterable)``\n\n The constructor builds a list whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a list, a copy is made and\n returned, similar to ``iterable[:]``. For example, ``list(\'abc\')``\n returns ``[\'a\', \'b\', \'c\']`` and ``list( (1, 2, 3) )`` returns ``[1,\n 2, 3]``. If no argument is given, the constructor creates a new\n empty list, ``[]``.\n\n Many other operations also produce lists, including the\n ``sorted()`` built-in.\n\n Lists implement all of the *common* and *mutable* sequence\n operations. Lists also provide the following additional method:\n\n sort(*, key=None, reverse=None)\n\n This method sorts the list in place, using only ``<``\n comparisons between items. Exceptions are not suppressed - if\n any comparison operations fail, the entire sort operation will\n fail (and the list will likely be left in a partially modified\n state).\n\n *key* specifies a function of one argument that is used to\n extract a comparison key from each list element (for example,\n ``key=str.lower``). The key corresponding to each item in the\n list is calculated once and then used for the entire sorting\n process. The default value of ``None`` means that list items are\n sorted directly without calculating a separate key value.\n\n The ``functools.cmp_to_key()`` utility is available to convert a\n 2.x style *cmp* function to a *key* function.\n\n *reverse* is a boolean value. If set to ``True``, then the list\n elements are sorted as if each comparison were reversed.\n\n This method modifies the sequence in place for economy of space\n when sorting a large sequence. To remind users that it operates\n by side effect, it does not return the sorted sequence (use\n ``sorted()`` to explicitly request a new sorted list instance).\n\n The ``sort()`` method is guaranteed to be stable. A sort is\n stable if it guarantees not to change the relative order of\n elements that compare equal --- this is helpful for sorting in\n multiple passes (for example, sort by department, then by salary\n grade).\n\n **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python makes the list appear\n empty for the duration, and raises ``ValueError`` if it can\n detect that the list has been mutated during a sort.\n\n\nTuples\n======\n\nTuples are immutable sequences, typically used to store collections of\nheterogeneous data (such as the 2-tuples produced by the\n``enumerate()`` built-in). Tuples are also used for cases where an\nimmutable sequence of homogeneous data is needed (such as allowing\nstorage in a ``set`` or ``dict`` instance).\n\nclass class tuple([iterable])\n\n Tuples may be constructed in a number of ways:\n\n * Using a pair of parentheses to denote the empty tuple: ``()``\n\n * Using a trailing comma for a singleton tuple: ``a,`` or ``(a,)``\n\n * Separating items with commas: ``a, b, c`` or ``(a, b, c)``\n\n * Using the ``tuple()`` built-in: ``tuple()`` or\n ``tuple(iterable)``\n\n The constructor builds a tuple whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a tuple, it is returned\n unchanged. For example, ``tuple(\'abc\')`` returns ``(\'a\', \'b\',\n \'c\')`` and ``tuple( [1, 2, 3] )`` returns ``(1, 2, 3)``. If no\n argument is given, the constructor creates a new empty tuple,\n ``()``.\n\n Note that it is actually the comma which makes a tuple, not the\n parentheses. The parentheses are optional, except in the empty\n tuple case, or when they are needed to avoid syntactic ambiguity.\n For example, ``f(a, b, c)`` is a function call with three\n arguments, while ``f((a, b, c))`` is a function call with a 3-tuple\n as the sole argument.\n\n Tuples implement all of the *common* sequence operations.\n\nFor heterogeneous collections of data where access by name is clearer\nthan access by index, ``collections.namedtuple()`` may be a more\nappropriate choice than a simple tuple object.\n\n\nRanges\n======\n\nThe ``range`` type represents an immutable sequence of numbers and is\ncommonly used for looping a specific number of times in ``for`` loops.\n\nclass class range(stop)\nclass class range(start, stop[, step])\n\n The arguments to the range constructor must be integers (either\n built-in ``int`` or any object that implements the ``__index__``\n special method). If the *step* argument is omitted, it defaults to\n ``1``. If the *start* argument is omitted, it defaults to ``0``. If\n *step* is zero, ``ValueError`` is raised.\n\n For a positive *step*, the contents of a range ``r`` are determined\n by the formula ``r[i] = start + step*i`` where ``i >= 0`` and\n ``r[i] < stop``.\n\n For a negative *step*, the contents of the range are still\n determined by the formula ``r[i] = start + step*i``, but the\n constraints are ``i >= 0`` and ``r[i] > stop``.\n\n A range object will be empty if ``r[0]`` does not meet the value\n constraint. Ranges do support negative indices, but these are\n interpreted as indexing from the end of the sequence determined by\n the positive indices.\n\n Ranges containing absolute values larger than ``sys.maxsize`` are\n permitted but some features (such as ``len()``) may raise\n ``OverflowError``.\n\n Range examples:\n\n >>> list(range(10))\n [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n >>> list(range(1, 11))\n [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n >>> list(range(0, 30, 5))\n [0, 5, 10, 15, 20, 25]\n >>> list(range(0, 10, 3))\n [0, 3, 6, 9]\n >>> list(range(0, -10, -1))\n [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]\n >>> list(range(0))\n []\n >>> list(range(1, 0))\n []\n\n Ranges implement all of the *common* sequence operations except\n concatenation and repetition (due to the fact that range objects\n can only represent sequences that follow a strict pattern and\n repetition and concatenation will usually violate that pattern).\n\nThe advantage of the ``range`` type over a regular ``list`` or\n``tuple`` is that a ``range`` object will always take the same (small)\namount of memory, no matter the size of the range it represents (as it\nonly stores the ``start``, ``stop`` and ``step`` values, calculating\nindividual items and subranges as needed).\n\nRange objects implement the ``collections.abc.Sequence`` ABC, and\nprovide features such as containment tests, element index lookup,\nslicing and support for negative indices (see *Sequence Types ---\nlist, tuple, range*):\n\n>>> r = range(0, 20, 2)\n>>> r\nrange(0, 20, 2)\n>>> 11 in r\nFalse\n>>> 10 in r\nTrue\n>>> r.index(10)\n5\n>>> r[5]\n10\n>>> r[:5]\nrange(0, 10, 2)\n>>> r[-1]\n18\n\nTesting range objects for equality with ``==`` and ``!=`` compares\nthem as sequences. That is, two range objects are considered equal if\nthey represent the same sequence of values. (Note that two range\nobjects that compare equal might have different ``start``, ``stop``\nand ``step`` attributes, for example ``range(0) == range(2, 1, 3)`` or\n``range(0, 3, 2) == range(0, 4, 2)``.)\n\nChanged in version 3.2: Implement the Sequence ABC. Support slicing\nand negative indices. Test ``int`` objects for membership in constant\ntime instead of iterating through all items.\n\nChanged in version 3.3: Define \'==\' and \'!=\' to compare range objects\nbased on the sequence of values they define (instead of comparing\nbased on object identity).\n\nNew in version 3.3: The ``start``, ``stop`` and ``step`` attributes.\n', - 'typesseq-mutable': "\nMutable Sequence Types\n**********************\n\nThe operations in the following table are defined on mutable sequence\ntypes. The ``collections.abc.MutableSequence`` ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, ``bytearray`` only\naccepts integers that meet the value restriction ``0 <= x <= 255``).\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | appends *x* to the end of the | |\n| | sequence (same as | |\n| | ``s[len(s):len(s)] = [x]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.clear()`` | removes all items from ``s`` | (5) |\n| | (same as ``del s[:]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.copy()`` | creates a shallow copy of ``s`` | (5) |\n| | (same as ``s[:]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(t)`` | extends *s* with the contents of | |\n| | *t* (same as ``s[len(s):len(s)] | |\n| | = t``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | inserts *x* into *s* at the | |\n| | index given by *i* (same as | |\n| | ``s[i:i] = [x]``) | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | retrieves the item at *i* and | (2) |\n| | also removes it from *s* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | remove the first item from *s* | (3) |\n| | where ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (4) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to ``-1``, so that by default\n the last item is removed and returned.\n\n3. ``remove`` raises ``ValueError`` when *x* is not found in *s*.\n\n4. The ``reverse()`` method modifies the sequence in place for economy\n of space when reversing a large sequence. To remind users that it\n operates by side effect, it does not return the reversed sequence.\n\n5. ``clear()`` and ``copy()`` are included for consistency with the\n interfaces of mutable containers that don't support slicing\n operations (such as ``dict`` and ``set``)\n\n New in version 3.3: ``clear()`` and ``copy()`` methods.\n", - 'unary': '\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary ``-`` (minus) operator yields the negation of its numeric\nargument.\n\nThe unary ``+`` (plus) operator yields its numeric argument unchanged.\n\nThe unary ``~`` (invert) operator yields the bitwise inversion of its\ninteger argument. The bitwise inversion of ``x`` is defined as\n``-(x+1)``. It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n``TypeError`` exception is raised.\n', - 'while': '\nThe ``while`` statement\n***********************\n\nThe ``while`` statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the ``else`` clause, if present, is\nexecuted and the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ngoes back to testing the expression.\n', - 'with': '\nThe ``with`` statement\n**********************\n\nThe ``with`` statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common\n``try``...``except``...``finally`` usage patterns to be encapsulated\nfor convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the ``with`` statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the ``with_item``)\n is evaluated to obtain a context manager.\n\n2. The context manager\'s ``__exit__()`` is loaded for later use.\n\n3. The context manager\'s ``__enter__()`` method is invoked.\n\n4. If a target was included in the ``with`` statement, the return\n value from ``__enter__()`` is assigned to it.\n\n Note: The ``with`` statement guarantees that if the ``__enter__()``\n method returns without an error, then ``__exit__()`` will always\n be called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s ``__exit__()`` method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to ``__exit__()``. Otherwise,\n three ``None`` arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the ``__exit__()`` method was false, the exception is\n reraised. If the return value was true, the exception is\n suppressed, and execution continues with the statement following\n the ``with`` statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from ``__exit__()`` is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple ``with`` statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` statement.\n', - 'yield': '\nThe ``yield`` statement\n***********************\n\n yield_stmt ::= yield_expression\n\nThe ``yield`` statement is only used when defining a generator\nfunction, and is only used in the body of the generator function.\nUsing a ``yield`` statement in a function definition is sufficient to\ncause that definition to create a generator function instead of a\nnormal function.\n\nWhen a generator function is called, it returns an iterator known as a\ngenerator iterator, or more commonly, a generator. The body of the\ngenerator function is executed by calling the ``next()`` function on\nthe generator repeatedly until it raises an exception.\n\nWhen a ``yield`` statement is executed, the state of the generator is\nfrozen and the value of ``expression_list`` is returned to\n``next()``\'s caller. By "frozen" we mean that all local state is\nretained, including the current bindings of local variables, the\ninstruction pointer, and the internal evaluation stack: enough\ninformation is saved so that the next time ``next()`` is invoked, the\nfunction can proceed exactly as if the ``yield`` statement were just\nanother external call.\n\nThe ``yield`` statement is allowed in the ``try`` clause of a ``try``\n... ``finally`` construct. If the generator is not resumed before it\nis finalized (by reaching a zero reference count or by being garbage\ncollected), the generator-iterator\'s ``close()`` method will be\ncalled, allowing any pending ``finally`` clauses to execute.\n\nWhen ``yield from `` is used, it treats the supplied expression\nas a subiterator, producing values from it until the underlying\niterator is exhausted.\n\n Changed in version 3.3: Added ``yield from `` to delegate\n control flow to a subiterator\n\nFor full details of ``yield`` semantics, refer to the *Yield\nexpressions* section.\n\nSee also:\n\n **PEP 0255** - Simple Generators\n The proposal for adding generators and the ``yield`` statement\n to Python.\n\n **PEP 0342** - Coroutines via Enhanced Generators\n The proposal to enhance the API and syntax of generators, making\n them usable as simple coroutines.\n\n **PEP 0380** - Syntax for Delegating to a Subgenerator\n The proposal to introduce the ``yield_from`` syntax, making\n delegation to sub-generators easy.\n'} + 'naming': '\nNaming and binding\n******************\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The string argument passed\nto the built-in functions "eval()" and "exec()" is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes comprehensions and generator\nexpressions since they are implemented using a function scope. This\nmeans that the following will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block,\nunless declared as "nonlocal". If a name is bound at the module\nlevel, it is a global variable. (The variables of the module code\nblock are local and global.) If a variable is used in a code block\nbut not defined there, it is a *free variable*.\n\nWhen a name is not found at all, a "NameError" exception is raised.\nIf the name refers to a local variable that has not been bound, a\n"UnboundLocalError" exception is raised. "UnboundLocalError" is a\nsubclass of "NameError".\n\nThe following constructs bind names: formal parameters to functions,\n"import" statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, "for" loop header, or after\n"as" in a "with" statement or "except" clause. The "import" statement\nof the form "from ... import *" binds all names defined in the\nimported module, except those beginning with an underscore. This form\nmay only be used at the module level.\n\nA target occurring in a "del" statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name).\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the "global" statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module "builtins". The global namespace is searched first. If\nthe name is not found there, the builtins namespace is searched. The\nglobal statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name "__builtins__" in its global\nnamespace; this should be a dictionary or a module (in the latter case\nthe module\'s dictionary is used). By default, when in the "__main__"\nmodule, "__builtins__" is the built-in module "builtins"; when in any\nother module, "__builtins__" is an alias for the dictionary of the\n"builtins" module itself. "__builtins__" can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n"__builtins__"; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should "import"\nthe "builtins" module and modify its attributes appropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n"__main__".\n\nThe "global" statement has the same scope as a name binding operation\nin the same block. If the nearest enclosing scope for a free variable\ncontains a global statement, the free variable is treated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n=================================\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- "import *" --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a "SyntaxError".\n\nThe "eval()" and "exec()" functions do not have access to the full\nenvironment for resolving names. Names may be resolved in the local\nand global namespaces of the caller. Free variables are not resolved\nin the nearest enclosing namespace, but in the global namespace. [1]\nThe "exec()" and "eval()" functions have optional arguments to\noverride the global and local namespace. If only one namespace is\nspecified, it is used for both.\n', + 'nonlocal': '\nThe "nonlocal" statement\n************************\n\n nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*\n\nThe "nonlocal" statement causes the listed identifiers to refer to\npreviously bound variables in the nearest enclosing scope. This is\nimportant because the default behavior for binding is to search the\nlocal namespace first. The statement allows encapsulated code to\nrebind variables outside of the local scope besides the global\n(module) scope.\n\nNames listed in a "nonlocal" statement, unlike to those listed in a\n"global" statement, must refer to pre-existing bindings in an\nenclosing scope (the scope in which a new binding should be created\ncannot be determined unambiguously).\n\nNames listed in a "nonlocal" statement must not collide with pre-\nexisting bindings in the local scope.\n\nSee also: **PEP 3104** - Access to Names in Outer Scopes\n\n The specification for the "nonlocal" statement.\n', + 'numbers': '\nNumeric literals\n****************\n\nThere are three types of numeric literals: integers, floating point\nnumbers, and imaginary numbers. There are no complex literals\n(complex numbers can be formed by adding a real number and an\nimaginary number).\n\nNote that numeric literals do not include a sign; a phrase like "-1"\nis actually an expression composed of the unary operator \'"-"\' and the\nliteral "1".\n', + 'numeric-types': '\nEmulating numeric types\n***********************\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "//", "%", "divmod()", "pow()",\n "**", "<<", ">>", "&", "^", "|"). For instance, to evaluate the\n expression "x + y", where *x* is an instance of a class that has an\n "__add__()" method, "x.__add__(y)" is called. The "__divmod__()"\n method should be the equivalent to using "__floordiv__()" and\n "__mod__()"; it should not be related to "__truediv__()". Note\n that "__pow__()" should be defined to accept an optional third\n argument if the ternary version of the built-in "pow()" function is\n to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "//", "%", "divmod()", "pow()",\n "**", "<<", ">>", "&", "^", "|") with reflected (swapped) operands.\n These functions are only called if the left operand does not\n support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "/=", "//=", "%=", "**=", "<<=",\n ">>=", "&=", "^=", "|="). These methods should attempt to do the\n operation in-place (modifying *self*) and return the result (which\n could be, but does not have to be, *self*). If a specific method\n is not defined, the augmented assignment falls back to the normal\n methods. For instance, to execute the statement "x += y", where\n *x* is an instance of a class that has an "__iadd__()" method,\n "x.__iadd__(y)" is called. If *x* is an instance of a class that\n does not define a "__iadd__()" method, "x.__add__(y)" and\n "y.__radd__(x)" are considered, as with the evaluation of "x + y".\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()". Also called whenever\n Python needs an integer object (such as in slicing, or in the\n built-in "bin()", "hex()" and "oct()" functions). Must return an\n integer.\n', + 'objects': '\nObjects, values and types\n*************************\n\n*Objects* are Python\'s abstraction for data. All data in a Python\nprogram is represented by objects or by relations between objects. (In\na sense, and in conformance to Von Neumann\'s model of a "stored\nprogram computer," code is also represented by objects.)\n\nEvery object has an identity, a type and a value. An object\'s\n*identity* never changes once it has been created; you may think of it\nas the object\'s address in memory. The \'"is"\' operator compares the\nidentity of two objects; the "id()" function returns an integer\nrepresenting its identity.\n\n**CPython implementation detail:** For CPython, "id(x)" is the memory\naddress where "x" is stored.\n\nAn object\'s type determines the operations that the object supports\n(e.g., "does it have a length?") and also defines the possible values\nfor objects of that type. The "type()" function returns an object\'s\ntype (which is an object itself). Like its identity, an object\'s\n*type* is also unchangeable. [1]\n\nThe *value* of some objects can change. Objects whose value can\nchange are said to be *mutable*; objects whose value is unchangeable\nonce they are created are called *immutable*. (The value of an\nimmutable container object that contains a reference to a mutable\nobject can change when the latter\'s value is changed; however the\ncontainer is still considered immutable, because the collection of\nobjects it contains cannot be changed. So, immutability is not\nstrictly the same as having an unchangeable value, it is more subtle.)\nAn object\'s mutability is determined by its type; for instance,\nnumbers, strings and tuples are immutable, while dictionaries and\nlists are mutable.\n\nObjects are never explicitly destroyed; however, when they become\nunreachable they may be garbage-collected. An implementation is\nallowed to postpone garbage collection or omit it altogether --- it is\na matter of implementation quality how garbage collection is\nimplemented, as long as no objects are collected that are still\nreachable.\n\n**CPython implementation detail:** CPython currently uses a reference-\ncounting scheme with (optional) delayed detection of cyclically linked\ngarbage, which collects most objects as soon as they become\nunreachable, but is not guaranteed to collect garbage containing\ncircular references. See the documentation of the "gc" module for\ninformation on controlling the collection of cyclic garbage. Other\nimplementations act differently and CPython may change. Do not depend\non immediate finalization of objects when they become unreachable (ex:\nalways close files).\n\nNote that the use of the implementation\'s tracing or debugging\nfacilities may keep objects alive that would normally be collectable.\nAlso note that catching an exception with a \'"try"..."except"\'\nstatement may keep objects alive.\n\nSome objects contain references to "external" resources such as open\nfiles or windows. It is understood that these resources are freed\nwhen the object is garbage-collected, but since garbage collection is\nnot guaranteed to happen, such objects also provide an explicit way to\nrelease the external resource, usually a "close()" method. Programs\nare strongly recommended to explicitly close such objects. The\n\'"try"..."finally"\' statement and the \'"with"\' statement provide\nconvenient ways to do this.\n\nSome objects contain references to other objects; these are called\n*containers*. Examples of containers are tuples, lists and\ndictionaries. The references are part of a container\'s value. In\nmost cases, when we talk about the value of a container, we imply the\nvalues, not the identities of the contained objects; however, when we\ntalk about the mutability of a container, only the identities of the\nimmediately contained objects are implied. So, if an immutable\ncontainer (like a tuple) contains a reference to a mutable object, its\nvalue changes if that mutable object is changed.\n\nTypes affect almost all aspects of object behavior. Even the\nimportance of object identity is affected in some sense: for immutable\ntypes, operations that compute new values may actually return a\nreference to any existing object with the same type and value, while\nfor mutable objects this is not allowed. E.g., after "a = 1; b = 1",\n"a" and "b" may or may not refer to the same object with the value\none, depending on the implementation, but after "c = []; d = []", "c"\nand "d" are guaranteed to refer to two different, unique, newly\ncreated empty lists. (Note that "c = d = []" assigns the same object\nto both "c" and "d".)\n', + 'operator-summary': '\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedences in Python,\nfrom lowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for comparisons, including\ntests, which all have the same precedence and chain from left to right\n--- see section *Comparisons* --- and exponentiation, which groups\nfrom right to left).\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| "lambda" | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| "if" -- "else" | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| "or" | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| "and" | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| "not" "x" | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| "in", "not in", "is", "is not", "<", "<=", ">", | Comparisons, including membership |\n| ">=", "!=", "==" | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| "|" | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| "^" | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| "&" | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| "<<", ">>" | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| "+", "-" | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| "*", "/", "//", "%" | Multiplication, division, remainder |\n+-------------------------------------------------+---------------------------------------+\n| "+x", "-x", "~x" | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| "**" | Exponentiation [6] |\n+-------------------------------------------------+---------------------------------------+\n| "x[index]", "x[index:index]", | Subscription, slicing, call, |\n| "x(arguments...)", "x.attribute" | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| "(expressions...)", "[expressions...]", "{key: | Binding or tuple display, list |\n| value...}", "{expressions...}" | display, dictionary display, set |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] While "abs(x%y) < abs(y)" is true mathematically, for floats\n it may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that "-1e-100 % 1e100" have the same\n sign as "1e100", the computed result is "-1e-100 + 1e100", which\n is numerically exactly equal to "1e100". The function\n "math.fmod()" returns a result whose sign matches the sign of the\n first argument instead, and so returns "-1e-100" in this case.\n Which approach is more appropriate depends on the application.\n\n[2] If x is very close to an exact integer multiple of y, it\'s\n possible for "x//y" to be one larger than "(x-x%y)//y" due to\n rounding. In such cases, Python returns the latter result, in\n order to preserve that "divmod(x,y)[0] * y + x % y" be very close\n to "x".\n\n[3] While comparisons between strings make sense at the byte\n level, they may be counter-intuitive to users. For example, the\n strings ""\\u00C7"" and ""\\u0327\\u0043"" compare differently, even\n though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using "unicodedata.normalize()".\n\n[4] Due to automatic garbage-collection, free lists, and the\n dynamic nature of descriptors, you may notice seemingly unusual\n behaviour in certain uses of the "is" operator, like those\n involving comparisons between instance methods, or constants.\n Check their documentation for more info.\n\n[5] The "%" operator is also used for string formatting; the same\n precedence applies.\n\n[6] The power operator "**" binds less tightly than an arithmetic\n or bitwise unary operator on its right, that is, "2**-1" is "0.5".\n', + 'pass': '\nThe "pass" statement\n********************\n\n pass_stmt ::= "pass"\n\n"pass" is a null operation --- when it is executed, nothing happens.\nIt is useful as a placeholder when a statement is required\nsyntactically, but no code needs to be executed, for example:\n\n def f(arg): pass # a function that does nothing (yet)\n\n class C: pass # a class with no methods (yet)\n', + 'power': '\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= primary ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): "-1**2" results in "-1".\n\nThe power operator has the same semantics as the built-in "pow()"\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type, and the result is of that type.\n\nFor int operands, the result has the same type as the operands unless\nthe second argument is negative; in that case, all arguments are\nconverted to float and a float result is delivered. For example,\n"10**2" returns "100", but "10**-2" returns "0.01".\n\nRaising "0.0" to a negative power results in a "ZeroDivisionError".\nRaising a negative number to a fractional power results in a "complex"\nnumber. (In earlier versions it raised a "ValueError".)\n', + 'raise': '\nThe "raise" statement\n*********************\n\n raise_stmt ::= "raise" [expression ["from" expression]]\n\nIf no expressions are present, "raise" re-raises the last exception\nthat was active in the current scope. If no exception is active in\nthe current scope, a "RuntimeError" exception is raised indicating\nthat this is an error.\n\nOtherwise, "raise" evaluates the first expression as the exception\nobject. It must be either a subclass or an instance of\n"BaseException". If it is a class, the exception instance will be\nobtained when needed by instantiating the class with no arguments.\n\nThe *type* of the exception is the exception instance\'s class, the\n*value* is the instance itself.\n\nA traceback object is normally created automatically when an exception\nis raised and attached to it as the "__traceback__" attribute, which\nis writable. You can create an exception and set your own traceback in\none step using the "with_traceback()" exception method (which returns\nthe same exception instance, with its traceback set to its argument),\nlike so:\n\n raise Exception("foo occurred").with_traceback(tracebackobj)\n\nThe "from" clause is used for exception chaining: if given, the second\n*expression* must be another exception class or instance, which will\nthen be attached to the raised exception as the "__cause__" attribute\n(which is writable). If the raised exception is not handled, both\nexceptions will be printed:\n\n >>> try:\n ... print(1 / 0)\n ... except Exception as exc:\n ... raise RuntimeError("Something bad happened") from exc\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n The above exception was the direct cause of the following exception:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nA similar mechanism works implicitly if an exception is raised inside\nan exception handler: the previous exception is then attached as the\nnew exception\'s "__context__" attribute:\n\n >>> try:\n ... print(1 / 0)\n ... except:\n ... raise RuntimeError("Something bad happened")\n ...\n Traceback (most recent call last):\n File "", line 2, in \n ZeroDivisionError: int division or modulo by zero\n\n During handling of the above exception, another exception occurred:\n\n Traceback (most recent call last):\n File "", line 4, in \n RuntimeError: Something bad happened\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information about handling exceptions is in section\n*The try statement*.\n', + 'return': '\nThe "return" statement\n**********************\n\n return_stmt ::= "return" [expression_list]\n\n"return" may only occur syntactically nested in a function definition,\nnot within a nested class definition.\n\nIf an expression list is present, it is evaluated, else "None" is\nsubstituted.\n\n"return" leaves the current function call with the expression list (or\n"None") as return value.\n\nWhen "return" passes control out of a "try" statement with a "finally"\nclause, that "finally" clause is executed before really leaving the\nfunction.\n\nIn a generator function, the "return" statement indicates that the\ngenerator is done and will cause "StopIteration" to be raised. The\nreturned value (if any) is used as an argument to construct\n"StopIteration" and becomes the "StopIteration.value" attribute.\n', + 'sequence-types': '\nEmulating container types\n*************************\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method "keys()".\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n', + 'shifting': '\nShifting operations\n*******************\n\nThe shifting operations have lower priority than the arithmetic\noperations:\n\n shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr\n\nThese operators accept integers as arguments. They shift the first\nargument to the left or right by the number of bits given by the\nsecond argument.\n\nA right shift by *n* bits is defined as floor division by "pow(2,n)".\nA left shift by *n* bits is defined as multiplication with "pow(2,n)".\n\nNote: In the current implementation, the right-hand operand is\n required to be at most "sys.maxsize". If the right-hand operand is\n larger than "sys.maxsize" an "OverflowError" exception is raised.\n', + 'slicings': '\nSlicings\n********\n\nA slicing selects a range of items in a sequence object (e.g., a\nstring, tuple or list). Slicings may be used as expressions or as\ntargets in assignment or "del" statements. The syntax for a slicing:\n\n slicing ::= primary "[" slice_list "]"\n slice_list ::= slice_item ("," slice_item)* [","]\n slice_item ::= expression | proper_slice\n proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]\n lower_bound ::= expression\n upper_bound ::= expression\n stride ::= expression\n\nThere is ambiguity in the formal syntax here: anything that looks like\nan expression list also looks like a slice list, so any subscription\ncan be interpreted as a slicing. Rather than further complicating the\nsyntax, this is disambiguated by defining that in this case the\ninterpretation as a subscription takes priority over the\ninterpretation as a slicing (this is the case if the slice list\ncontains no proper slice).\n\nThe semantics for a slicing are as follows. The primary must evaluate\nto a mapping object, and it is indexed (using the same "__getitem__()"\nmethod as normal subscription) with a key that is constructed from the\nslice list, as follows. If the slice list contains at least one\ncomma, the key is a tuple containing the conversion of the slice\nitems; otherwise, the conversion of the lone slice item is the key.\nThe conversion of a slice item that is an expression is that\nexpression. The conversion of a proper slice is a slice object (see\nsection *The standard type hierarchy*) whose "start", "stop" and\n"step" attributes are the values of the expressions given as lower\nbound, upper bound and stride, respectively, substituting "None" for\nmissing expressions.\n', + 'specialattrs': '\nSpecial Attributes\n******************\n\nThe implementation adds a few special read-only attributes to several\nobject types, where they are relevant. Some of these are not reported\nby the "dir()" built-in function.\n\nobject.__dict__\n\n A dictionary or other mapping object used to store an object\'s\n (writable) attributes.\n\ninstance.__class__\n\n The class to which a class instance belongs.\n\nclass.__bases__\n\n The tuple of base classes of a class object.\n\nclass.__name__\n\n The name of the class or type.\n\nclass.__qualname__\n\n The *qualified name* of the class or type.\n\n New in version 3.3.\n\nclass.__mro__\n\n This attribute is a tuple of classes that are considered when\n looking for base classes during method resolution.\n\nclass.mro()\n\n This method can be overridden by a metaclass to customize the\n method resolution order for its instances. It is called at class\n instantiation, and its result is stored in "__mro__".\n\nclass.__subclasses__()\n\n Each class keeps a list of weak references to its immediate\n subclasses. This method returns a list of all those references\n still alive. Example:\n\n >>> int.__subclasses__()\n []\n\n-[ Footnotes ]-\n\n[1] Additional information on these special methods may be found\n in the Python Reference Manual (*Basic customization*).\n\n[2] As a consequence, the list "[1, 2]" is considered equal to\n "[1.0, 2.0]", and similarly for tuples.\n\n[3] They must have since the parser can\'t tell the type of the\n operands.\n\n[4] Cased characters are those with general category property\n being one of "Lu" (Letter, uppercase), "Ll" (Letter, lowercase),\n or "Lt" (Letter, titlecase).\n\n[5] To format only a tuple you should therefore provide a\n singleton tuple whose only element is the tuple to be formatted.\n', + 'specialnames': '\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "type(x).__getitem__(x, i)".\nExcept where mentioned, attempts to execute an operation raise an\nexception when no appropriate method is defined (typically\n"AttributeError" or "TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called when the instance is created. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])". As a special constraint on\n constructors, no value may be returned; doing so will cause a\n "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the latter two situations can be resolved by storing "None" in\n "sys.last_traceback". Circular references which are garbage are\n detected when the option cycle detector is enabled (it\'s on by\n default), but can only be cleaned up if there are no Python-\n level "__del__()" methods involved. Refer to the documentation\n for the "gc" module for more information about how "__del__()"\n methods are handled by the cycle detector, particularly the\n description of the "garbage" value.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)""\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable").\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n .__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. If defined in a\n class, *__slots__* reserves space for the declared variables and\n prevents the automatic creation of *__dict__* and *__weakref__* for\n each instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using "type()". The class body is\nexecuted in a new namespace and the class name is bound locally to the\nresult of "type(name, bases, namespace)".\n\nThe class creation process can be customised by passing the\n"metaclass" keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both "MyClass" and "MySubclass" are instances\nof "Meta":\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then "type()" is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n "type()", then it is used directly as the metaclass\n\n* if an instance of "type()" is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. "type(cls)") of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with "TypeError".\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a "__prepare__" attribute,\nit is called as "namespace = metaclass.__prepare__(name, bases,\n**kwds)" (where the additional keyword arguments, if any, come from\nthe class definition).\n\nIf the metaclass has no "__prepare__" attribute, then the class\nnamespace is initialised as an empty "dict()" instance.\n\nSee also: **PEP 3115** - Metaclasses in Python 3000\n\n Introduced the "__prepare__" namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as "exec(body, globals(),\nnamespace)". The key difference from a normal call to "exec()" is that\nlexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling "metaclass(name, bases,\nnamespace, **kwds)" (the additional keywords passed here are the same\nas those passed to "__prepare__").\n\nThis class object is the one that will be referenced by the zero-\nargument form of "super()". "__class__" is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either "__class__" or "super". This allows the zero argument form\nof "super()" to correctly identify the class being defined based on\nlexical scoping, while the class or instance that was used to make the\ncurrent call is identified based on the first argument passed to the\nmethod.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also: **PEP 3135** - New super\n\n Describes the implicit "__class__" closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n"collections.OrderedDict" to remember the order that class members\nwere defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s "__prepare__()" method which returns an\nempty "collections.OrderedDict". That mapping records the methods and\nattributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s "__new__()" method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called "members".\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method "keys()".\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "//", "%", "divmod()", "pow()",\n "**", "<<", ">>", "&", "^", "|"). For instance, to evaluate the\n expression "x + y", where *x* is an instance of a class that has an\n "__add__()" method, "x.__add__(y)" is called. The "__divmod__()"\n method should be the equivalent to using "__floordiv__()" and\n "__mod__()"; it should not be related to "__truediv__()". Note\n that "__pow__()" should be defined to accept an optional third\n argument if the ternary version of the built-in "pow()" function is\n to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "/", "//", "%", "divmod()", "pow()",\n "**", "<<", ">>", "&", "^", "|") with reflected (swapped) operands.\n These functions are only called if the left operand does not\n support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "/=", "//=", "%=", "**=", "<<=",\n ">>=", "&=", "^=", "|="). These methods should attempt to do the\n operation in-place (modifying *self*) and return the result (which\n could be, but does not have to be, *self*). If a specific method\n is not defined, the augmented assignment falls back to the normal\n methods. For instance, to execute the statement "x += y", where\n *x* is an instance of a class that has an "__iadd__()" method,\n "x.__iadd__(y)" is called. If *x* is an instance of a class that\n does not define a "__iadd__()" method, "x.__add__(y)" and\n "y.__radd__(x)" are considered, as with the evaluation of "x + y".\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()". Also called whenever\n Python needs an integer object (such as in slicing, or in the\n built-in "bin()", "hex()" and "oct()" functions). Must return an\n integer.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n\n-[ Footnotes ]-\n\n[1] It *is* possible in some cases to change an object\'s type,\n under certain controlled conditions. It generally isn\'t a good\n idea though, since it can lead to some very strange behaviour if\n it is handled incorrectly.\n\n[2] For operands of the same type, it is assumed that if the non-\n reflected method (such as "__add__()") fails the operation is not\n supported, which is why the reflected method is not called.\n', + 'string-methods': '\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see "str.format()",\n*Format String Syntax* and *String Formatting*) and the other based on\nC "printf" style formatting that handles a narrower range of types and\nis slightly harder to use correctly, but is often faster for the cases\nit can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the "re" module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter "\'\xc3\x9f\'" is equivalent to ""ss"".\n Since it is already lowercase, "lower()" would do nothing to "\'\xc3\x9f\'";\n "casefold()" converts it to ""ss"".\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is a space).\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is "\'utf-8\'". *errors* may be given to set a different\n error handling scheme. The default for *errors* is "\'strict\'",\n meaning that encoding errors raise a "UnicodeError". Other possible\n values are "\'ignore\'", "\'replace\'", "\'xmlcharrefreplace\'",\n "\'backslashreplace\'" and any other name registered via\n "codecs.register_error()", see section *Codec Base Classes*. For a\n list of possible encodings, see section *Standard Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to "str.format(**mapping)", except that "mapping" is used\n directly and not copied to a "dict". This is useful if for example\n "mapping" is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character "c"\n is alphanumeric if one of the following returns "True":\n "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()".\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use "keyword.iskeyword()" to test for reserved identifiers such as\n "def" and "class".\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when "repr()" is\n invoked on a string. It has no bearing on the handling of strings\n written to "sys.stdout" or "sys.stderr".)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A "TypeError" will be raised if there are\n any non-string values in *iterable*, including "bytes" objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n "str.translate()".\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example, "\' 1 2 3 \'.split()" returns "[\'1\', \'2\', \'3\']", and\n "\' 1 2 3 \'.split(None, 1)" returns "[\'1\', \'2 3 \']".\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example, "\'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()" returns "[\'ab\n c\', \'\', \'de fg\', \'kl\']", while the same call with\n "splitlines(True)" returns "[\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']".\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line.\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n "s.swapcase().swapcase() == s".\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(map)\n\n Return a copy of the *s* where all characters have been mapped\n through the *map* which must be a dictionary of Unicode ordinals\n (integers) to Unicode ordinals, strings or "None". Unmapped\n characters are left untouched. Characters mapped to "None" are\n deleted.\n\n You can use "str.maketrans()" to create a translation map from\n character-to-character mappings in different formats.\n\n Note: An even more flexible approach is to create a custom\n character mapping codec using the "codecs" module (see\n "encodings.cp1251" for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to "len(s)".\n', + 'strings': '\nString and Bytes literals\n*************************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "R" | "U"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'" | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | stringescapeseq\n longstringitem ::= longstringchar | stringescapeseq\n shortstringchar ::= \n longstringchar ::= \n stringescapeseq ::= "\\" \n\n bytesliteral ::= bytesprefix(shortbytes | longbytes)\n bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"\n shortbytes ::= "\'" shortbytesitem* "\'" | \'"\' shortbytesitem* \'"\'\n longbytes ::= "\'\'\'" longbytesitem* "\'\'\'" | \'"""\' longbytesitem* \'"""\'\n shortbytesitem ::= shortbyteschar | bytesescapeseq\n longbytesitem ::= longbyteschar | bytesescapeseq\n shortbyteschar ::= \n longbyteschar ::= \n bytesescapeseq ::= "\\" \n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the "stringprefix" or "bytesprefix"\nand the rest of the literal. The source character set is defined by\nthe encoding declaration; it is UTF-8 if no encoding declaration is\ngiven in the source file; see section *Encoding declarations*.\n\nIn plain English: Both types of literals can be enclosed in matching\nsingle quotes ("\'") or double quotes ("""). They can also be enclosed\nin matching groups of three single or double quotes (these are\ngenerally referred to as *triple-quoted strings*). The backslash\n("\\") character is used to escape characters that otherwise have a\nspecial meaning, such as newline, backslash itself, or the quote\ncharacter.\n\nBytes literals are always prefixed with "\'b\'" or "\'B\'"; they produce\nan instance of the "bytes" type instead of the "str" type. They may\nonly contain ASCII characters; bytes with a numeric value of 128 or\ngreater must be expressed with escapes.\n\nAs of Python 3.3 it is possible again to prefix unicode strings with a\n"u" prefix to simplify maintenance of dual 2.x and 3.x codebases.\n\nBoth string and bytes literals may optionally be prefixed with a\nletter "\'r\'" or "\'R\'"; such strings are called *raw strings* and treat\nbackslashes as literal characters. As a result, in string literals,\n"\'\\U\'" and "\'\\u\'" escapes in raw strings are not treated specially.\nGiven that Python 2.x\'s raw unicode literals behave differently than\nPython 3.x\'s the "\'ur\'" syntax is not supported.\n\n New in version 3.3: The "\'rb\'" prefix of raw bytes literals has\n been added as a synonym of "\'br\'".\n\n New in version 3.3: Support for the unicode legacy literal\n ("u\'value\'") was reintroduced to simplify the maintenance of dual\n Python 2.x and 3.x codebases. See **PEP 414** for more information.\n\nIn triple-quoted strings, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the string. (A "quote" is the character used to open the\nstring, i.e. either "\'" or """.)\n\nUnless an "\'r\'" or "\'R\'" prefix is present, escape sequences in\nstrings are interpreted according to rules similar to those used by\nStandard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n+-------------------+-----------------------------------+---------+\n| "\\ooo" | Character with octal value *ooo* | (1,3) |\n+-------------------+-----------------------------------+---------+\n| "\\xhh" | Character with hex value *hh* | (2,3) |\n+-------------------+-----------------------------------+---------+\n\nEscape sequences only recognized in string literals are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\N{name}" | Character named *name* in the | (4) |\n+-------------------+-----------------------------------+---------+\n| "\\uxxxx" | Character with 16-bit hex value | (5) |\n+-------------------+-----------------------------------+---------+\n| "\\Uxxxxxxxx" | Character with 32-bit hex value | (6) |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. As in Standard C, up to three octal digits are accepted.\n\n2. Unlike in Standard C, exactly two hex digits are required.\n\n3. In a bytes literal, hexadecimal and octal escapes denote the\n byte with the given value. In a string literal, these escapes\n denote a Unicode character with the given value.\n\n4. Changed in version 3.3: Support for name aliases [1] has been\n added.\n\n5. Individual code units which form parts of a surrogate pair can\n be encoded using this escape sequence. Exactly four hex digits are\n required.\n\n6. Any Unicode character can be encoded this way. Exactly eight\n hex digits are required.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the string*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences only recognized in string\nliterals fall into the category of unrecognized escapes for bytes\nliterals.\n\nEven in a raw string, string quotes can be escaped with a backslash,\nbut the backslash remains in the string; for example, "r"\\""" is a\nvalid string literal consisting of two characters: a backslash and a\ndouble quote; "r"\\"" is not a valid string literal (even a raw string\ncannot end in an odd number of backslashes). Specifically, *a raw\nstring cannot end in a single backslash* (since the backslash would\nescape the following quote character). Note also that a single\nbackslash followed by a newline is interpreted as those two characters\nas part of the string, *not* as a line continuation.\n', + 'subscriptions': '\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object that supports subscription,\ne.g. a list or dictionary. User-defined objects can support\nsubscription by defining a "__getitem__()" method.\n\nFor built-in objects, there are two types of objects that support\nsubscription:\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to\nan integer or a slice (as discussed in the following section).\n\nThe formal syntax makes no special provision for negative indices in\nsequences; however, built-in sequences all provide a "__getitem__()"\nmethod that interprets negative indices by adding the length of the\nsequence to the index (so that "x[-1]" selects the last item of "x").\nThe resulting value must be a nonnegative integer less than the number\nof items in the sequence, and the subscription selects the item whose\nindex is that value (counting from zero). Since the support for\nnegative indices and slicing occurs in the object\'s "__getitem__()"\nmethod, subclasses overriding this method will need to explicitly add\nthat support.\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n', + 'truth': '\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an "if" or\n"while" condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* "None"\n\n* "False"\n\n* zero of any numeric type, for example, "0", "0.0", "0j".\n\n* any empty sequence, for example, "\'\'", "()", "[]".\n\n* any empty mapping, for example, "{}".\n\n* instances of user-defined classes, if the class defines a\n "__bool__()" or "__len__()" method, when that method returns the\n integer zero or "bool" value "False". [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn "0" or "False" for false and "1" or "True" for true, unless\notherwise stated. (Important exception: the Boolean operations "or"\nand "and" always return one of their operands.)\n', + 'try': '\nThe "try" statement\n*******************\n\nThe "try" statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression ["as" target]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nThe "except" clause(s) specify one or more exception handlers. When no\nexception occurs in the "try" clause, no exception handler is\nexecuted. When an exception occurs in the "try" suite, a search for an\nexception handler is started. This search inspects the except clauses\nin turn until one is found that matches the exception. An expression-\nless except clause, if present, must be last; it matches any\nexception. For an except clause with an expression, that expression\nis evaluated, and the clause matches the exception if the resulting\nobject is "compatible" with the exception. An object is compatible\nwith an exception if it is the class or a base class of the exception\nobject or a tuple containing an item compatible with the exception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire "try" statement raised\nthe exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified after the "as" keyword in that except clause, if\npresent, and the except clause\'s suite is executed. All except\nclauses must have an executable block. When the end of this block is\nreached, execution continues normally after the entire try statement.\n(This means that if two nested handlers exist for the same exception,\nand the exception occurs in the try clause of the inner handler, the\nouter handler will not handle the exception.)\n\nWhen an exception has been assigned using "as target", it is cleared\nat the end of the except clause. This is as if\n\n except E as N:\n foo\n\nwas translated to\n\n except E as N:\n try:\n foo\n finally:\n del N\n\nThis means the exception must be assigned to a different name to be\nable to refer to it after the except clause. Exceptions are cleared\nbecause with the traceback attached to them, they form a reference\ncycle with the stack frame, keeping all locals in that frame alive\nuntil the next garbage collection occurs.\n\nBefore an except clause\'s suite is executed, details about the\nexception are stored in the "sys" module and can be access via\n"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of the\nexception class, the exception instance and a traceback object (see\nsection *The standard type hierarchy*) identifying the point in the\nprogram where the exception occurred. "sys.exc_info()" values are\nrestored to their previous values (before the call) when returning\nfrom a function that handled an exception.\n\nThe optional "else" clause is executed if and when control flows off\nthe end of the "try" clause. [2] Exceptions in the "else" clause are\nnot handled by the preceding "except" clauses.\n\nIf "finally" is present, it specifies a \'cleanup\' handler. The "try"\nclause is executed, including any "except" and "else" clauses. If an\nexception occurs in any of the clauses and is not handled, the\nexception is temporarily saved. The "finally" clause is executed. If\nthere is a saved exception it is re-raised at the end of the "finally"\nclause. If the "finally" clause raises another exception, the saved\nexception is set as the context of the new exception. If the "finally"\nclause executes a "return" or "break" statement, the saved exception\nis discarded:\n\n def f():\n try:\n 1/0\n finally:\n return 42\n\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the "finally" clause.\n\nWhen a "return", "break" or "continue" statement is executed in the\n"try" suite of a "try"..."finally" statement, the "finally" clause is\nalso executed \'on the way out.\' A "continue" statement is illegal in\nthe "finally" clause. (The reason is a problem with the current\nimplementation --- this restriction may be lifted in the future).\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the "raise" statement to\ngenerate exceptions may be found in section *The raise statement*.\n', + 'types': '\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.), although such additions\nwill often be provided via the standard library instead.\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name "None". It\n is used to signify the absence of a value in many situations, e.g.,\n it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n "NotImplemented". Numeric methods and rich comparison methods may\n return this value if they do not implement the operation for the\n operands provided. (The interpreter will then try the reflected\n operation, or some other fallback, depending on the operator.) Its\n truth value is true.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the literal "..." or the\n built-in name "Ellipsis". Its truth value is true.\n\n"numbers.Number"\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n "numbers.Integral"\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are two types of integers:\n\n Integers ("int")\n\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans ("bool")\n These represent the truth values False and True. The two\n objects representing the values "False" and "True" are the\n only Boolean objects. The Boolean type is a subtype of the\n integer type, and Boolean values behave like the values 0 and\n 1, respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ""False"" or\n ""True"" are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers.\n\n "numbers.Real" ("float")\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these is\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n "numbers.Complex" ("complex")\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number "z" can be retrieved through the read-only\n attributes "z.real" and "z.imag".\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function "len()" returns the number of items\n of a sequence. When the length of a sequence is *n*, the index set\n contains the numbers 0, 1, ..., *n*-1. Item *i* of sequence *a* is\n selected by "a[i]".\n\n Sequences also support slicing: "a[i:j]" selects all items with\n index *k* such that *i* "<=" *k* "<" *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: "a[i:j:k]" selects all items of *a* with index *x* where\n "x = i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n A string is a sequence of values that represent Unicode\n codepoints. All the codepoints in range "U+0000 - U+10FFFF"\n can be represented in a string. Python doesn\'t have a "chr"\n type, and every character in the string is represented as a\n string object with length "1". The built-in function "ord()"\n converts a character to its codepoint (as an integer);\n "chr()" converts an integer in range "0 - 10FFFF" to the\n corresponding character. "str.encode()" can be used to\n convert a "str" to "bytes" using the given encoding, and\n "bytes.decode()" can be used to achieve the opposite.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Bytes\n A bytes object is an immutable array. The items are 8-bit\n bytes, represented by integers in the range 0 <= x < 256.\n Bytes literals (like "b\'abc\'") and the built-in function\n "bytes()" can be used to construct bytes objects. Also,\n bytes objects can be decoded to strings via the "decode()"\n method.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and "del" (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in "bytearray()" constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module "array" provides an additional example of a\n mutable sequence type, as does the "collections" module.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function "len()"\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., "1" and\n "1.0"), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n "set()" constructor and can be modified afterwards by several\n methods, such as "add()".\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in "frozenset()" constructor. As a frozenset is immutable\n and *hashable*, it can be used again as an element of another\n set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation "a[k]" selects the item indexed by "k"\n from the mapping "a"; this can be used in expressions and as the\n target of assignments or "del" statements. The built-in function\n "len()" returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., "1" and "1.0")\n then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the "{...}"\n notation (see section *Dictionary displays*).\n\n The extension modules "dbm.ndbm" and "dbm.gnu" provide\n additional examples of mapping types, as does the "collections"\n module.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +---------------------------+---------------------------------+-------------+\n +===========================+=================================+=============+\n | "__doc__" | The function\'s documentation | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__name__" | The function\'s name | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__qualname__" | The function\'s *qualified name* | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__module__" | The name of the module the | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__defaults__" | A tuple containing default | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__code__" | The code object representing | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__globals__" | A reference to the dictionary | Read-only |\n +---------------------------+---------------------------------+-------------+\n | "__dict__" | The namespace supporting | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__closure__" | "None" or a tuple of cells that | Read-only |\n +---------------------------+---------------------------------+-------------+\n | "__annotations__" | A dict containing annotations | Writable |\n +---------------------------+---------------------------------+-------------+\n | "__kwdefaults__" | A dict containing defaults for | Writable |\n +---------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n Instance methods\n An instance method object combines a class, a class instance and\n any callable object (normally a user-defined function).\n\n Special read-only attributes: "__self__" is the class instance\n object, "__func__" is the function object; "__doc__" is the\n method\'s documentation (same as "__func__.__doc__"); "__name__"\n is the method name (same as "__func__.__name__"); "__module__"\n is the name of the module the method was defined in, or "None"\n if unavailable.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object or a class\n method object.\n\n When an instance method object is created by retrieving a user-\n defined function object from a class via one of its instances,\n its "__self__" attribute is the instance, and the method object\n is said to be bound. The new method\'s "__func__" attribute is\n the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the "__func__"\n attribute of the new instance is not the original method object\n but its "__func__" attribute.\n\n When an instance method object is created by retrieving a class\n method object from a class or instance, its "__self__" attribute\n is the class itself, and its "__func__" attribute is the\n function object underlying the class method.\n\n When an instance method object is called, the underlying\n function ("__func__") is called, inserting the class instance\n ("__self__") in front of the argument list. For instance, when\n "C" is a class which contains a definition for a function "f()",\n and "x" is an instance of "C", calling "x.f(1)" is equivalent to\n calling "C.f(x, 1)".\n\n When an instance method object is derived from a class method\n object, the "class instance" stored in "__self__" will actually\n be the class itself, so that calling either "x.f(1)" or "C.f(1)"\n is equivalent to calling "f(C,1)" where "f" is the underlying\n function.\n\n Note that the transformation from function object to instance\n method object happens each time the attribute is retrieved from\n the instance. In some cases, a fruitful optimization is to\n assign the attribute to a local variable and call that local\n variable. Also notice that this transformation only happens for\n user-defined functions; other callable objects (and all non-\n callable objects) are retrieved without transformation. It is\n also important to note that user-defined functions which are\n attributes of a class instance are not converted to bound\n methods; this *only* happens when the function is an attribute\n of the class.\n\n Generator functions\n A function or method which uses the "yield" statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s "iterator.__next__()" method will cause the\n function to execute until it provides a value using the "yield"\n statement. When the function executes a "return" statement or\n falls off the end, a "StopIteration" exception is raised and the\n iterator will have reached the end of the set of values to be\n returned.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are "len()" and "math.sin()"\n ("math" is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: "__doc__" is the function\'s documentation\n string, or "None" if unavailable; "__name__" is the function\'s\n name; "__self__" is set to "None" (but see the next item);\n "__module__" is the name of the module the function was defined\n in or "None" if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n "alist.append()", assuming *alist* is a list object. In this\n case, the special read-only attribute "__self__" is set to the\n object denoted by *alist*.\n\n Classes\n Classes are callable. These objects normally act as factories\n for new instances of themselves, but variations are possible for\n class types that override "__new__()". The arguments of the\n call are passed to "__new__()" and, in the typical case, to\n "__init__()" to initialize the new instance.\n\n Class Instances\n Instances of arbitrary classes can be made callable by defining\n a "__call__()" method in their class.\n\nModules\n Modules are a basic organizational unit of Python code, and are\n created by the *import system* as invoked either by the "import"\n statement (see "import"), or by calling functions such as\n "importlib.import_module()" and built-in "__import__()". A module\n object has a namespace implemented by a dictionary object (this is\n the dictionary referenced by the "__globals__" attribute of\n functions defined in the module). Attribute references are\n translated to lookups in this dictionary, e.g., "m.x" is equivalent\n to "m.__dict__["x"]". A module object does not contain the code\n object used to initialize the module (since it isn\'t needed once\n the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n\n Special read-only attribute: "__dict__" is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: "__name__" is the module\'s name;\n "__doc__" is the module\'s documentation string, or "None" if\n unavailable; "__file__" is the pathname of the file from which the\n module was loaded, if it was loaded from a file. The "__file__"\n attribute may be missing for certain types of modules, such as C\n modules that are statically linked into the interpreter; for\n extension modules loaded dynamically from a shared library, it is\n the pathname of the shared library file.\n\nCustom classes\n Custom class types are typically created by class definitions (see\n section *Class definitions*). A class has a namespace implemented\n by a dictionary object. Class attribute references are translated\n to lookups in this dictionary, e.g., "C.x" is translated to\n "C.__dict__["x"]" (although there are a number of hooks which allow\n for other means of locating attributes). When the attribute name is\n not found there, the attribute search continues in the base\n classes. This search of the base classes uses the C3 method\n resolution order which behaves correctly even in the presence of\n \'diamond\' inheritance structures where there are multiple\n inheritance paths leading back to a common ancestor. Additional\n details on the C3 MRO used by Python can be found in the\n documentation accompanying the 2.3 release at\n http://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class "C", say) would yield a\n class method object, it is transformed into an instance method\n object whose "__self__" attributes is "C". When it would yield a\n static method object, it is transformed into the object wrapped by\n the static method object. See section *Implementing Descriptors*\n for another way in which attributes retrieved from a class may\n differ from those actually contained in its "__dict__".\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: "__name__" is the class name; "__module__" is\n the module name in which the class was defined; "__dict__" is the\n dictionary containing the class\'s namespace; "__bases__" is a tuple\n (possibly empty or a singleton) containing the base classes, in the\n order of their occurrence in the base class list; "__doc__" is the\n class\'s documentation string, or None if undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object, it is transformed into an instance method object\n whose "__self__" attribute is the instance. Static method and\n class method objects are also transformed; see above under\n "Classes". See section *Implementing Descriptors* for another way\n in which attributes of a class retrieved via its instances may\n differ from the objects actually stored in the class\'s "__dict__".\n If no class attribute is found, and the object\'s class has a\n "__getattr__()" method, that is called to satisfy the lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n "__setattr__()" or "__delattr__()" method, this is called instead\n of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: "__dict__" is the attribute dictionary;\n "__class__" is the instance\'s class.\n\nI/O objects (also known as file objects)\n A *file object* represents an open file. Various shortcuts are\n available to create file objects: the "open()" built-in function,\n and also "os.popen()", "os.fdopen()", and the "makefile()" method\n of socket objects (and perhaps by other functions or methods\n provided by extension modules).\n\n The objects "sys.stdin", "sys.stdout" and "sys.stderr" are\n initialized to file objects corresponding to the interpreter\'s\n standard input, output and error streams; they are all open in text\n mode and therefore follow the interface defined by the\n "io.TextIOBase" abstract class.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: "co_name" gives the function name;\n "co_argcount" is the number of positional arguments (including\n arguments with default values); "co_nlocals" is the number of\n local variables used by the function (including arguments);\n "co_varnames" is a tuple containing the names of the local\n variables (starting with the argument names); "co_cellvars" is a\n tuple containing the names of local variables that are\n referenced by nested functions; "co_freevars" is a tuple\n containing the names of free variables; "co_code" is a string\n representing the sequence of bytecode instructions; "co_consts"\n is a tuple containing the literals used by the bytecode;\n "co_names" is a tuple containing the names used by the bytecode;\n "co_filename" is the filename from which the code was compiled;\n "co_firstlineno" is the first line number of the function;\n "co_lnotab" is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); "co_stacksize" is the required stack size\n (including local variables); "co_flags" is an integer encoding a\n number of flags for the interpreter.\n\n The following flag bits are defined for "co_flags": bit "0x04"\n is set if the function uses the "*arguments" syntax to accept an\n arbitrary number of positional arguments; bit "0x08" is set if\n the function uses the "**keywords" syntax to accept arbitrary\n keyword arguments; bit "0x20" is set if the function is a\n generator.\n\n Future feature declarations ("from __future__ import division")\n also use bits in "co_flags" to indicate whether a code object\n was compiled with a particular feature enabled: bit "0x2000" is\n set if the function was compiled with future division enabled;\n bits "0x10" and "0x1000" were used in earlier versions of\n Python.\n\n Other bits in "co_flags" are reserved for internal use.\n\n If a code object represents a function, the first item in\n "co_consts" is the documentation string of the function, or\n "None" if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: "f_back" is to the previous stack\n frame (towards the caller), or "None" if this is the bottom\n stack frame; "f_code" is the code object being executed in this\n frame; "f_locals" is the dictionary used to look up local\n variables; "f_globals" is used for global variables;\n "f_builtins" is used for built-in (intrinsic) names; "f_lasti"\n gives the precise instruction (this is an index into the\n bytecode string of the code object).\n\n Special writable attributes: "f_trace", if not "None", is a\n function called at the start of each source code line (this is\n used by the debugger); "f_lineno" is the current line number of\n the frame --- writing to this from within a trace function jumps\n to the given line (only for the bottom-most frame). A debugger\n can implement a Jump command (aka Set Next Statement) by writing\n to f_lineno.\n\n Traceback objects\n Traceback objects represent a stack trace of an exception. A\n traceback object is created when an exception occurs. When the\n search for an exception handler unwinds the execution stack, at\n each unwound level a traceback object is inserted in front of\n the current traceback. When an exception handler is entered,\n the stack trace is made available to the program. (See section\n *The try statement*.) It is accessible as the third item of the\n tuple returned by "sys.exc_info()". When the program contains no\n suitable handler, the stack trace is written (nicely formatted)\n to the standard error stream; if the interpreter is interactive,\n it is also made available to the user as "sys.last_traceback".\n\n Special read-only attributes: "tb_next" is the next level in the\n stack trace (towards the frame where the exception occurred), or\n "None" if there is no next level; "tb_frame" points to the\n execution frame of the current level; "tb_lineno" gives the line\n number where the exception occurred; "tb_lasti" indicates the\n precise instruction. The line number and last instruction in\n the traceback may differ from the line number of its frame\n object if the exception occurred in a "try" statement with no\n matching except clause or with a finally clause.\n\n Slice objects\n Slice objects are used to represent slices for "__getitem__()"\n methods. They are also created by the built-in "slice()"\n function.\n\n Special read-only attributes: "start" is the lower bound; "stop"\n is the upper bound; "step" is the step value; each is "None" if\n omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the slice that the slice object\n would describe if applied to a sequence of *length* items.\n It returns a tuple of three integers; respectively these are\n the *start* and *stop* indices and the *step* or stride\n length of the slice. Missing or out-of-bounds indices are\n handled in a manner consistent with regular slices.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n "staticmethod()" constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in "classmethod()" constructor.\n', + 'typesfunctions': '\nFunctions\n*********\n\nFunction objects are created by function definitions. The only\noperation on a function object is to call it: "func(argument-list)".\n\nThere are really two flavors of function objects: built-in functions\nand user-defined functions. Both support the same operation (to call\nthe function), but the implementation is different, hence the\ndifferent object types.\n\nSee *Function definitions* for more information.\n', + 'typesmapping': '\nMapping Types --- "dict"\n************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built-\nin "list", "set", and "tuple" classes, and the "collections" module.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as "1" and "1.0") then they can be used interchangeably to index\nthe same dictionary entry. (Note however, that since computers store\nfloating-point numbers as approximations it is usually unwise to use\nthem as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of "key:\nvalue" pairs within braces, for example: "{\'jack\': 4098, \'sjoerd\':\n4127}" or "{4098: \'jack\', 4127: \'sjoerd\'}", or by the "dict"\nconstructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterator*\n object. Each item in the iterable must itself be an iterator with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to "{"one": 1, "two": 2, "three": 3}":\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a "KeyError" if\n *key* is not in the map.\n\n If a subclass of dict defines a method "__missing__()", if the\n key *key* is not present, the "d[key]" operation calls that\n method with the key *key* as argument. The "d[key]" operation\n then returns or raises whatever is returned or raised by the\n "__missing__(key)" call if the key is not present. No other\n operations or methods invoke "__missing__()". If "__missing__()"\n is not defined, "KeyError" is raised. "__missing__()" must be a\n method; it cannot be an instance variable:\n\n >>> class Counter(dict):\n ... def __missing__(self, key):\n ... return 0\n >>> c = Counter()\n >>> c[\'red\']\n 0\n >>> c[\'red\'] += 1\n >>> c[\'red\']\n 1\n\n See "collections.Counter" for a complete implementation\n including other methods helpful for accumulating and managing\n tallies.\n\n d[key] = value\n\n Set "d[key]" to *value*.\n\n del d[key]\n\n Remove "d[key]" from *d*. Raises a "KeyError" if *key* is not\n in the map.\n\n key in d\n\n Return "True" if *d* has a key *key*, else "False".\n\n key not in d\n\n Equivalent to "not key in d".\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for "iter(d.keys())".\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n classmethod fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n "fromkeys()" is a class method that returns a new dictionary.\n *value* defaults to "None".\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to "None", so\n that this method never raises a "KeyError".\n\n items()\n\n Return a new view of the dictionary\'s items ("(key, value)"\n pairs). See the *documentation of view objects*.\n\n keys()\n\n Return a new view of the dictionary\'s keys. See the\n *documentation of view objects*.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a "KeyError" is raised.\n\n popitem()\n\n Remove and return an arbitrary "(key, value)" pair from the\n dictionary.\n\n "popitem()" is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling "popitem()" raises a "KeyError".\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to "None".\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return "None".\n\n "update()" accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: "d.update(red=1,\n blue=2)".\n\n values()\n\n Return a new view of the dictionary\'s values. See the\n *documentation of view objects*.\n\nSee also: "types.MappingProxyType" can be used to create a read-only\n view of a "dict".\n\n\nDictionary view objects\n=======================\n\nThe objects returned by "dict.keys()", "dict.values()" and\n"dict.items()" are *view objects*. They provide a dynamic view on the\ndictionary\'s entries, which means that when the dictionary changes,\nthe view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of "(key, value)") in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of "(value, key)" pairs using\n "zip()": "pairs = zip(d.values(), d.keys())". Another way to\n create the same list is "pairs = [(v, k) for (k, v) in d.items()]".\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a "RuntimeError" or fail to iterate over all entries.\n\nx in dictview\n\n Return "True" if *x* is in the underlying dictionary\'s keys, values\n or items (in the latter case, *x* should be a "(key, value)"\n tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that "(key, value)" pairs are unique\nand hashable, then the items view is also set-like. (Values views are\nnot treated as set-like since the entries are generally not unique.)\nFor set-like views, all of the operations defined for the abstract\nbase class "collections.abc.Set" are available (for example, "==",\n"<", or "^").\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.keys()\n >>> values = dishes.values()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n >>> keys ^ {\'sausage\', \'juice\'}\n {\'juice\', \'sausage\', \'bacon\', \'spam\'}\n', + 'typesmethods': '\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as "append()" on lists)\nand class instance methods. Built-in methods are described with the\ntypes that support them.\n\nIf you access a method (a function defined in a class namespace)\nthrough an instance, you get a special object: a *bound method* (also\ncalled *instance method*) object. When called, it will add the "self"\nargument to the argument list. Bound methods have two special read-\nonly attributes: "m.__self__" is the object on which the method\noperates, and "m.__func__" is the function implementing the method.\nCalling "m(arg-1, arg-2, ..., arg-n)" is completely equivalent to\ncalling "m.__func__(m.__self__, arg-1, arg-2, ..., arg-n)".\n\nLike function objects, bound method objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object ("meth.__func__"), setting method\nattributes on bound methods is disallowed. Attempting to set an\nattribute on a method results in an "AttributeError" being raised. In\norder to set a method attribute, you need to explicitly set it on the\nunderlying function object:\n\n >>> class C:\n ... def method(self):\n ... pass\n ...\n >>> c = C()\n >>> c.method.whoami = \'my name is method\' # can\'t set on the method\n Traceback (most recent call last):\n File "", line 1, in \n AttributeError: \'method\' object has no attribute \'whoami\'\n >>> c.method.__func__.whoami = \'my name is method\'\n >>> c.method.whoami\n \'my name is method\'\n\nSee *The standard type hierarchy* for more information.\n', + 'typesmodules': '\nModules\n*******\n\nThe only special operation on a module is attribute access: "m.name",\nwhere *m* is a module and *name* accesses a name defined in *m*\'s\nsymbol table. Module attributes can be assigned to. (Note that the\n"import" statement is not, strictly speaking, an operation on a module\nobject; "import foo" does not require a module object named *foo* to\nexist, rather it requires an (external) *definition* for a module\nnamed *foo* somewhere.)\n\nA special attribute of every module is "__dict__". This is the\ndictionary containing the module\'s symbol table. Modifying this\ndictionary will actually change the module\'s symbol table, but direct\nassignment to the "__dict__" attribute is not possible (you can write\n"m.__dict__[\'a\'] = 1", which defines "m.a" to be "1", but you can\'t\nwrite "m.__dict__ = {}"). Modifying "__dict__" directly is not\nrecommended.\n\nModules built into the interpreter are written like this: "". If loaded from a file, they are written as\n"".\n', + 'typesseq': '\nSequence Types --- "list", "tuple", "range"\n*******************************************\n\nThere are three basic sequence types: lists, tuples, and range\nobjects. Additional sequence types tailored for processing of *binary\ndata* and *text strings* are described in dedicated sections.\n\n\nCommon Sequence Operations\n==========================\n\nThe operations in the following table are supported by most sequence\ntypes, both mutable and immutable. The "collections.abc.Sequence" ABC\nis provided to make it easier to correctly implement these operations\non custom sequence types.\n\nThis table lists the sequence operations sorted in ascending priority\n(operations in the same box have the same priority). In the table,\n*s* and *t* are sequences of the same type, *n*, *i*, *j* and *k* are\nintegers and *x* is an arbitrary object that meets any type and value\nrestrictions imposed by *s*.\n\nThe "in" and "not in" operations have the same priorities as the\ncomparison operations. The "+" (concatenation) and "*" (repetition)\noperations have the same priority as the corresponding numeric\noperations.\n\n+----------------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+============================+==================================+============+\n| "x in s" | "True" if an item of *s* is | (1) |\n+----------------------------+----------------------------------+------------+\n| "x not in s" | "False" if an item of *s* is | (1) |\n+----------------------------+----------------------------------+------------+\n| "s + t" | the concatenation of *s* and *t* | (6)(7) |\n+----------------------------+----------------------------------+------------+\n| "s * n" or "n * s" | *n* shallow copies of *s* | (2)(7) |\n+----------------------------+----------------------------------+------------+\n| "s[i]" | *i*th item of *s*, origin 0 | (3) |\n+----------------------------+----------------------------------+------------+\n| "s[i:j]" | slice of *s* from *i* to *j* | (3)(4) |\n+----------------------------+----------------------------------+------------+\n| "s[i:j:k]" | slice of *s* from *i* to *j* | (3)(5) |\n+----------------------------+----------------------------------+------------+\n+----------------------------+----------------------------------+------------+\n+----------------------------+----------------------------------+------------+\n+----------------------------+----------------------------------+------------+\n| "s.index(x[, i[, j]])" | index of the first occurrence of | (8) |\n+----------------------------+----------------------------------+------------+\n+----------------------------+----------------------------------+------------+\n\nSequences of the same type also support comparisons. In particular,\ntuples and lists are compared lexicographically by comparing\ncorresponding elements. This means that to compare equal, every\nelement must compare equal and the two sequences must be of the same\ntype and have the same length. (For full details see *Comparisons* in\nthe language reference.)\n\nNotes:\n\n1. While the "in" and "not in" operations are used only for simple\n containment testing in the general case, some specialised sequences\n (such as "str", "bytes" and "bytearray") also use them for\n subsequence testing:\n\n >>> "gg" in "eggs"\n True\n\n2. Values of *n* less than "0" are treated as "0" (which yields an\n empty sequence of the same type as *s*). Note also that the copies\n are shallow; nested structures are not copied. This often haunts\n new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that "[[]]" is a one-element list containing\n an empty list, so all three elements of "[[]] * 3" are (pointers\n to) this single empty list. Modifying any of the elements of\n "lists" modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n3. If *i* or *j* is negative, the index is relative to the end of\n the string: "len(s) + i" or "len(s) + j" is substituted. But note\n that "-0" is still "0".\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that "i <= k < j". If *i* or *j* is\n greater than "len(s)", use "len(s)". If *i* is omitted or "None",\n use "0". If *j* is omitted or "None", use "len(s)". If *i* is\n greater than or equal to *j*, the slice is empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index "x = i + n*k" such that "0 <= n <\n (j-i)/k". In other words, the indices are "i", "i+k", "i+2*k",\n "i+3*k" and so on, stopping when *j* is reached (but never\n including *j*). If *i* or *j* is greater than "len(s)", use\n "len(s)". If *i* or *j* are omitted or "None", they become "end"\n values (which end depends on the sign of *k*). Note, *k* cannot be\n zero. If *k* is "None", it is treated like "1".\n\n6. Concatenating immutable sequences always results in a new\n object. This means that building up a sequence by repeated\n concatenation will have a quadratic runtime cost in the total\n sequence length. To get a linear runtime cost, you must switch to\n one of the alternatives below:\n\n * if concatenating "str" objects, you can build a list and use\n "str.join()" at the end or else write to a "io.StringIO" instance\n and retrieve its value when complete\n\n * if concatenating "bytes" objects, you can similarly use\n "bytes.join()" or "io.BytesIO", or you can do in-place\n concatenation with a "bytearray" object. "bytearray" objects are\n mutable and have an efficient overallocation mechanism\n\n * if concatenating "tuple" objects, extend a "list" instead\n\n * for other types, investigate the relevant class documentation\n\n7. Some sequence types (such as "range") only support item\n sequences that follow specific patterns, and hence don\'t support\n sequence concatenation or repetition.\n\n8. "index" raises "ValueError" when *x* is not found in *s*. When\n supported, the additional arguments to the index method allow\n efficient searching of subsections of the sequence. Passing the\n extra arguments is roughly equivalent to using "s[i:j].index(x)",\n only without copying any data and with the returned index being\n relative to the start of the sequence rather than the start of the\n slice.\n\n\nImmutable Sequence Types\n========================\n\nThe only operation that immutable sequence types generally implement\nthat is not also implemented by mutable sequence types is support for\nthe "hash()" built-in.\n\nThis support allows immutable sequences, such as "tuple" instances, to\nbe used as "dict" keys and stored in "set" and "frozenset" instances.\n\nAttempting to hash an immutable sequence that contains unhashable\nvalues will result in "TypeError".\n\n\nMutable Sequence Types\n======================\n\nThe operations in the following table are defined on mutable sequence\ntypes. The "collections.abc.MutableSequence" ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, "bytearray" only\naccepts integers that meet the value restriction "0 <= x <= 255").\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j:k] = t" | the elements of "s[i:j:k]" are | (1) |\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s.clear()" | removes all items from "s" (same | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.copy()" | creates a shallow copy of "s" | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s.pop([i])" | retrieves the item at *i* and | (2) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.remove(x)" | remove the first item from *s* | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.reverse()" | reverses the items of *s* in | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to "-1", so that by default\n the last item is removed and returned.\n\n3. "remove" raises "ValueError" when *x* is not found in *s*.\n\n4. The "reverse()" method modifies the sequence in place for\n economy of space when reversing a large sequence. To remind users\n that it operates by side effect, it does not return the reversed\n sequence.\n\n5. "clear()" and "copy()" are included for consistency with the\n interfaces of mutable containers that don\'t support slicing\n operations (such as "dict" and "set")\n\n New in version 3.3: "clear()" and "copy()" methods.\n\n\nLists\n=====\n\nLists are mutable sequences, typically used to store collections of\nhomogeneous items (where the precise degree of similarity will vary by\napplication).\n\nclass class list([iterable])\n\n Lists may be constructed in several ways:\n\n * Using a pair of square brackets to denote the empty list: "[]"\n\n * Using square brackets, separating items with commas: "[a]",\n "[a, b, c]"\n\n * Using a list comprehension: "[x for x in iterable]"\n\n * Using the type constructor: "list()" or "list(iterable)"\n\n The constructor builds a list whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a list, a copy is made and\n returned, similar to "iterable[:]". For example, "list(\'abc\')"\n returns "[\'a\', \'b\', \'c\']" and "list( (1, 2, 3) )" returns "[1, 2,\n 3]". If no argument is given, the constructor creates a new empty\n list, "[]".\n\n Many other operations also produce lists, including the "sorted()"\n built-in.\n\n Lists implement all of the *common* and *mutable* sequence\n operations. Lists also provide the following additional method:\n\n sort(*, key=None, reverse=None)\n\n This method sorts the list in place, using only "<" comparisons\n between items. Exceptions are not suppressed - if any comparison\n operations fail, the entire sort operation will fail (and the\n list will likely be left in a partially modified state).\n\n "sort()" accepts two arguments that can only be passed by\n keyword (*keyword-only arguments*):\n\n *key* specifies a function of one argument that is used to\n extract a comparison key from each list element (for example,\n "key=str.lower"). The key corresponding to each item in the list\n is calculated once and then used for the entire sorting process.\n The default value of "None" means that list items are sorted\n directly without calculating a separate key value.\n\n The "functools.cmp_to_key()" utility is available to convert a\n 2.x style *cmp* function to a *key* function.\n\n *reverse* is a boolean value. If set to "True", then the list\n elements are sorted as if each comparison were reversed.\n\n This method modifies the sequence in place for economy of space\n when sorting a large sequence. To remind users that it operates\n by side effect, it does not return the sorted sequence (use\n "sorted()" to explicitly request a new sorted list instance).\n\n The "sort()" method is guaranteed to be stable. A sort is\n stable if it guarantees not to change the relative order of\n elements that compare equal --- this is helpful for sorting in\n multiple passes (for example, sort by department, then by salary\n grade).\n\n **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python makes the list appear\n empty for the duration, and raises "ValueError" if it can detect\n that the list has been mutated during a sort.\n\n\nTuples\n======\n\nTuples are immutable sequences, typically used to store collections of\nheterogeneous data (such as the 2-tuples produced by the "enumerate()"\nbuilt-in). Tuples are also used for cases where an immutable sequence\nof homogeneous data is needed (such as allowing storage in a "set" or\n"dict" instance).\n\nclass class tuple([iterable])\n\n Tuples may be constructed in a number of ways:\n\n * Using a pair of parentheses to denote the empty tuple: "()"\n\n * Using a trailing comma for a singleton tuple: "a," or "(a,)"\n\n * Separating items with commas: "a, b, c" or "(a, b, c)"\n\n * Using the "tuple()" built-in: "tuple()" or "tuple(iterable)"\n\n The constructor builds a tuple whose items are the same and in the\n same order as *iterable*\'s items. *iterable* may be either a\n sequence, a container that supports iteration, or an iterator\n object. If *iterable* is already a tuple, it is returned\n unchanged. For example, "tuple(\'abc\')" returns "(\'a\', \'b\', \'c\')"\n and "tuple( [1, 2, 3] )" returns "(1, 2, 3)". If no argument is\n given, the constructor creates a new empty tuple, "()".\n\n Note that it is actually the comma which makes a tuple, not the\n parentheses. The parentheses are optional, except in the empty\n tuple case, or when they are needed to avoid syntactic ambiguity.\n For example, "f(a, b, c)" is a function call with three arguments,\n while "f((a, b, c))" is a function call with a 3-tuple as the sole\n argument.\n\n Tuples implement all of the *common* sequence operations.\n\nFor heterogeneous collections of data where access by name is clearer\nthan access by index, "collections.namedtuple()" may be a more\nappropriate choice than a simple tuple object.\n\n\nRanges\n======\n\nThe "range" type represents an immutable sequence of numbers and is\ncommonly used for looping a specific number of times in "for" loops.\n\nclass class range(stop)\nclass class range(start, stop[, step])\n\n The arguments to the range constructor must be integers (either\n built-in "int" or any object that implements the "__index__"\n special method). If the *step* argument is omitted, it defaults to\n "1". If the *start* argument is omitted, it defaults to "0". If\n *step* is zero, "ValueError" is raised.\n\n For a positive *step*, the contents of a range "r" are determined\n by the formula "r[i] = start + step*i" where "i >= 0" and "r[i] <\n stop".\n\n For a negative *step*, the contents of the range are still\n determined by the formula "r[i] = start + step*i", but the\n constraints are "i >= 0" and "r[i] > stop".\n\n A range object will be empty if "r[0]" does not meet the value\n constraint. Ranges do support negative indices, but these are\n interpreted as indexing from the end of the sequence determined by\n the positive indices.\n\n Ranges containing absolute values larger than "sys.maxsize" are\n permitted but some features (such as "len()") may raise\n "OverflowError".\n\n Range examples:\n\n >>> list(range(10))\n [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n >>> list(range(1, 11))\n [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n >>> list(range(0, 30, 5))\n [0, 5, 10, 15, 20, 25]\n >>> list(range(0, 10, 3))\n [0, 3, 6, 9]\n >>> list(range(0, -10, -1))\n [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]\n >>> list(range(0))\n []\n >>> list(range(1, 0))\n []\n\n Ranges implement all of the *common* sequence operations except\n concatenation and repetition (due to the fact that range objects\n can only represent sequences that follow a strict pattern and\n repetition and concatenation will usually violate that pattern).\n\nThe advantage of the "range" type over a regular "list" or "tuple" is\nthat a "range" object will always take the same (small) amount of\nmemory, no matter the size of the range it represents (as it only\nstores the "start", "stop" and "step" values, calculating individual\nitems and subranges as needed).\n\nRange objects implement the "collections.abc.Sequence" ABC, and\nprovide features such as containment tests, element index lookup,\nslicing and support for negative indices (see *Sequence Types ---\nlist, tuple, range*):\n\n>>> r = range(0, 20, 2)\n>>> r\nrange(0, 20, 2)\n>>> 11 in r\nFalse\n>>> 10 in r\nTrue\n>>> r.index(10)\n5\n>>> r[5]\n10\n>>> r[:5]\nrange(0, 10, 2)\n>>> r[-1]\n18\n\nTesting range objects for equality with "==" and "!=" compares them as\nsequences. That is, two range objects are considered equal if they\nrepresent the same sequence of values. (Note that two range objects\nthat compare equal might have different "start", "stop" and "step"\nattributes, for example "range(0) == range(2, 1, 3)" or "range(0, 3,\n2) == range(0, 4, 2)".)\n\nChanged in version 3.2: Implement the Sequence ABC. Support slicing\nand negative indices. Test "int" objects for membership in constant\ntime instead of iterating through all items.\n\nChanged in version 3.3: Define \'==\' and \'!=\' to compare range objects\nbased on the sequence of values they define (instead of comparing\nbased on object identity).\n\nNew in version 3.3: The "start", "stop" and "step" attributes.\n', + 'typesseq-mutable': '\nMutable Sequence Types\n**********************\n\nThe operations in the following table are defined on mutable sequence\ntypes. The "collections.abc.MutableSequence" ABC is provided to make\nit easier to correctly implement these operations on custom sequence\ntypes.\n\nIn the table *s* is an instance of a mutable sequence type, *t* is any\niterable object and *x* is an arbitrary object that meets any type and\nvalue restrictions imposed by *s* (for example, "bytearray" only\naccepts integers that meet the value restriction "0 <= x <= 255").\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s[i:j:k] = t" | the elements of "s[i:j:k]" are | (1) |\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s.clear()" | removes all items from "s" (same | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.copy()" | creates a shallow copy of "s" | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n+--------------------------------+----------------------------------+-----------------------+\n| "s.pop([i])" | retrieves the item at *i* and | (2) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.remove(x)" | remove the first item from *s* | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| "s.reverse()" | reverses the items of *s* in | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The optional argument *i* defaults to "-1", so that by default\n the last item is removed and returned.\n\n3. "remove" raises "ValueError" when *x* is not found in *s*.\n\n4. The "reverse()" method modifies the sequence in place for\n economy of space when reversing a large sequence. To remind users\n that it operates by side effect, it does not return the reversed\n sequence.\n\n5. "clear()" and "copy()" are included for consistency with the\n interfaces of mutable containers that don\'t support slicing\n operations (such as "dict" and "set")\n\n New in version 3.3: "clear()" and "copy()" methods.\n', + 'unary': '\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary "-" (minus) operator yields the negation of its numeric\nargument.\n\nThe unary "+" (plus) operator yields its numeric argument unchanged.\n\nThe unary "~" (invert) operator yields the bitwise inversion of its\ninteger argument. The bitwise inversion of "x" is defined as\n"-(x+1)". It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n"TypeError" exception is raised.\n', + 'while': '\nThe "while" statement\n*********************\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n', + 'with': '\nThe "with" statement\n********************\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', + 'yield': '\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nThe "yield" statement is only used when defining a generator function,\nand is only used in the body of the generator function. Using a\n"yield" statement in a function definition is sufficient to cause that\ndefinition to create a generator function instead of a normal\nfunction.\n\nWhen a generator function is called, it returns an iterator known as a\ngenerator iterator, or more commonly, a generator. The body of the\ngenerator function is executed by calling the "next()" function on the\ngenerator repeatedly until it raises an exception.\n\nWhen a "yield" statement is executed, the state of the generator is\nfrozen and the value of "expression_list" is returned to "next()"\'s\ncaller. By "frozen" we mean that all local state is retained,\nincluding the current bindings of local variables, the instruction\npointer, and the internal evaluation stack: enough information is\nsaved so that the next time "next()" is invoked, the function can\nproceed exactly as if the "yield" statement were just another external\ncall.\n\nThe "yield" statement is allowed in the "try" clause of a "try" ...\n"finally" construct. If the generator is not resumed before it is\nfinalized (by reaching a zero reference count or by being garbage\ncollected), the generator-iterator\'s "close()" method will be called,\nallowing any pending "finally" clauses to execute.\n\nWhen "yield from " is used, it treats the supplied expression as\na subiterator, producing values from it until the underlying iterator\nis exhausted.\n\n Changed in version 3.3: Added "yield from " to delegate\n control flow to a subiterator\n\nFor full details of "yield" semantics, refer to the *Yield\nexpressions* section.\n\nSee also: **PEP 0255** - Simple Generators\n\n The proposal for adding generators and the "yield" statement to\n Python.\n\n **PEP 0342** - Coroutines via Enhanced Generators\n The proposal to enhance the API and syntax of generators, making\n them usable as simple coroutines.\n\n **PEP 0380** - Syntax for Delegating to a Subgenerator\n The proposal to introduce the "yield_from" syntax, making\n delegation to sub-generators easy.\n'} diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -62,6 +62,7 @@ SMTP_SSL_PORT = 465 CRLF = "\r\n" bCRLF = b"\r\n" +_MAXLINE = 8192 # more than 8 times larger than RFC 821, 4.5.3 OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) @@ -364,7 +365,7 @@ self.file = self.sock.makefile('rb') while 1: try: - line = self.file.readline() + line = self.file.readline(_MAXLINE + 1) except socket.error as e: self.close() raise SMTPServerDisconnected("Connection unexpectedly closed: " @@ -374,6 +375,8 @@ raise SMTPServerDisconnected("Connection unexpectedly closed") if self.debuglevel > 0: print('reply:', repr(line), file=stderr) + if len(line) > _MAXLINE: + raise SMTPResponseException(500, "Line too long.") resp.append(line[4:].strip(b' \t\r\n')) code = line[:3] # Check that the error code is syntactically correct. diff --git a/Lib/test/mock_socket.py b/Lib/test/mock_socket.py --- a/Lib/test/mock_socket.py +++ b/Lib/test/mock_socket.py @@ -21,8 +21,13 @@ """ def __init__(self, lines): self.lines = lines - def readline(self): - return self.lines.pop(0) + b'\r\n' + def readline(self, limit=-1): + result = self.lines.pop(0) + b'\r\n' + if limit >= 0: + # Re-insert the line, removing the \r\n we added. + self.lines.insert(0, result[limit:-2]) + result = result[:limit] + return result def close(self): pass diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -569,6 +569,33 @@ HOST, self.port, 'localhost', 3) + at unittest.skipUnless(threading, 'Threading required for this test.') +class TooLongLineTests(unittest.TestCase): + respdata = b'250 OK' + (b'.' * smtplib._MAXLINE * 2) + b'\n' + + def setUp(self): + self.old_stdout = sys.stdout + self.output = io.StringIO() + sys.stdout = self.output + + self.evt = threading.Event() + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.settimeout(15) + self.port = support.bind_port(self.sock) + servargs = (self.evt, self.respdata, self.sock) + threading.Thread(target=server, args=servargs).start() + self.evt.wait() + self.evt.clear() + + def tearDown(self): + self.evt.wait() + sys.stdout = self.old_stdout + + def testLineTooLong(self): + self.assertRaises(smtplib.SMTPResponseException, smtplib.SMTP, + HOST, self.port, 'localhost', 3) + + sim_users = {'Mr.A at somewhere.com':'John A', 'Ms.B at xn--fo-fka.com':'Sally B', 'Mrs.C at somewhereesle.com':'Ruth C', @@ -885,7 +912,8 @@ def test_main(verbose=None): support.run_unittest(GeneralTests, DebuggingServerTests, NonConnectingTests, - BadHELOServerTests, SMTPSimTests) + BadHELOServerTests, SMTPSimTests, + TooLongLineTests) if __name__ == '__main__': test_main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,19 +2,133 @@ Python News +++++++++++ +What's New in Python 3.3.5 release candidate 1? +=============================================== + +*Release date: XXXX-XX-XX* + +Core and Builtins +----------------- + +- Issue #20437: Fixed 21 potential bugs when deleting objects references. + +- Issue #20538: UTF-7 incremental decoder produced inconsistant string when + input was truncated in BASE64 section. + +Library +------- + +- Issue #14983: email.generator now always adds a line end after each MIME + boundary marker, instead of doing so only when there is an epilogue. This + fixes an RFC compliance bug and solves an issue with signed MIME parts. + +- Issue #20540: Fix a performance regression (vs. Python 3.2) when layering + a multiprocessing Connection over a TCP socket. For small payloads, Nagle's + algorithm would introduce idle delays before the entire transmission of a + message. + +- Issue #16983: the new email header parsing code will now decode encoded words + that are (incorrectly) surrounded by quotes, and register a defect. + +- Issue #19772: email.generator no longer mutates the message object when + doing a down-transform from 8bit to 7bit CTEs. + +- Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably + filters out illegal values and correctly allows any valid prefix length. + +- Issue #17369: get_filename was raising an exception if the filename + parameter's RFC2231 encoding was broken in certain ways. This was + a regression relative to python2. + +- Issue #20013: Some imap servers disconnect if the current mailbox is + deleted, and imaplib did not handle that case gracefully. Now it + handles the 'bye' correctly. + +- Issue #19920: TarFile.list() no longer fails when outputs a listing + containing non-encodable characters. Based on patch by Vajrasky Kok. + +- Issue #20515: Fix NULL pointer dereference introduced by issue #20368. + +- Issue #19186: Restore namespacing of expat symbols inside the pyexpat module. + +- Issue #20426: When passing the re.DEBUG flag, re.compile() displays the + debug output every time it is called, regardless of the compilation cache. + +- Issue #20368: The null character now correctly passed from Tcl to Python. + Improved error handling in variables-related commands. + +- Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline + translation settings. + +- Issue #20288: fix handling of invalid numeric charrefs in HTMLParser. + +- Issue #20424: Python implementation of io.StringIO now supports lone surrogates. + +- Issue #19456: ntpath.join() now joins relative paths correctly when a drive + is present. + +- Issue #19077: tempfile.TemporaryDirectory cleanup is now most likely + successful when called during nulling out of modules during shutdown. + Misleading exception no longer raised when resource warning is emitted + during shutdown. + +- Issue #20367: Fix behavior of concurrent.futures.as_completed() for + duplicate arguments. Patch by Glenn Langford. + +- Issue #8260: The read(), readline() and readlines() methods of + codecs.StreamReader returned incomplete data when were called after + readline() or read(size). Based on patch by Amaury Forgeot d'Arc. + +IDLE +---- + +- Issue #20406: Use Python application icons for Idle window title bars. + Patch mostly by Serhiy Storchaka. + +- Update the python.gif icon for the Idle classbrowser and pathbowser + from the old green snake to the new new blue and yellow snakes. + +- Issue #17721: Remove non-functional configuration dialog help button until we + make it actually gives some help when clicked. Patch by Guilherme Sim?es. + +Tests +----- + +- Issue #20532: Tests which use _testcapi are now marked as CPython only. + +- Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. + +- Issue #19990: Added tests for the imghdr module. Based on patch by + Claudiu Popa. + +- Issue #20474: Fix test_socket "unexpected success" failures on OS X 10.7+. + +Documentation +------------- + +- Issue #20488: Importlib is no longer *an* implementation of import, it's *the* + implementation. + + +What's New in Python 3.3.4? +=========================== + +*Release date: 09-Feb-2014* + +Library +------- + +- Issue #20374: Fix build warnings of the readline module with libedit on Mac. + + What's New in Python 3.3.4 release candidate 1? =============================================== -*Not yet released, see sections below for changes released in 3.3.3* +*Release date: 26-Jan-2014* Core and Builtins ----------------- -- Issue #20437: Fixed 21 potential bugs when deleting objects references. - -- Issue #20538: UTF-7 incremental decoder produced inconsistant string when - input was truncated in BASE64 section. - - Issue #17825: Cursor "^" is correctly positioned for SyntaxError and IndentationError. @@ -50,66 +164,8 @@ Library ------- -- Issue #14983: email.generator now always adds a line end after each MIME - boundary marker, instead of doing so only when there is an epilogue. This - fixes an RFC compliance bug and solves an issue with signed MIME parts. - -- Issue #20540: Fix a performance regression (vs. Python 3.2) when layering - a multiprocessing Connection over a TCP socket. For small payloads, Nagle's - algorithm would introduce idle delays before the entire transmission of a - message. - -- Issue #16983: the new email header parsing code will now decode encoded words - that are (incorrectly) surrounded by quotes, and register a defect. - -- Issue #19772: email.generator no longer mutates the message object when - doing a down-transform from 8bit to 7bit CTEs. - -- Issue #18805: the netmask/hostmask parsing in ipaddress now more reliably - filters out illegal values and correctly allows any valid prefix length. - -- Issue #17369: get_filename was raising an exception if the filename - parameter's RFC2231 encoding was broken in certain ways. This was - a regression relative to python2. - -- Issue #20013: Some imap servers disconnect if the current mailbox is - deleted, and imaplib did not handle that case gracefully. Now it - handles the 'bye' correctly. - -- Issue #19920: TarFile.list() no longer fails when outputs a listing - containing non-encodable characters. Based on patch by Vajrasky Kok. - -- Issue #20515: Fix NULL pointer dereference introduced by issue #20368. - -- Issue #19186: Restore namespacing of expat symbols inside the pyexpat module. - -- Issue #20426: When passing the re.DEBUG flag, re.compile() displays the - debug output every time it is called, regardless of the compilation cache. - -- Issue #20368: The null character now correctly passed from Tcl to Python. - Improved error handling in variables-related commands. - -- Issue #20435: Fix _pyio.StringIO.getvalue() to take into account newline - translation settings. - -- Issue #20288: fix handling of invalid numeric charrefs in HTMLParser. - -- Issue #20424: Python implementation of io.StringIO now supports lone surrogates. - -- Issue #19456: ntpath.join() now joins relative paths correctly when a drive - is present. - -- Issue #19077: tempfile.TemporaryDirectory cleanup is now most likely - successful when called during nulling out of modules during shutdown. - Misleading exception no longer raised when resource warning is emitted - during shutdown. - -- Issue #20367: Fix behavior of concurrent.futures.as_completed() for - duplicate arguments. Patch by Glenn Langford. - -- Issue #8260: The read(), readline() and readlines() methods of - codecs.StreamReader returned incomplete data when were called after - readline() or read(size). Based on patch by Amaury Forgeot d'Arc. +- Issue #16042: CVE-2013-1752: smtplib: Limit amount of data read by + limiting the call to readline(). Original patch by Christian Heimes. - Issue #20317: ExitStack.__exit__ could create a self-referential loop if an exception raised by a cleanup operation already had its context set @@ -333,15 +389,6 @@ IDLE ---- -- Issue #20406: Use Python application icons for Idle window title bars. - Patch mostly by Serhiy Storchaka. - -- Update the python.gif icon for the Idle classbrowser and pathbowser - from the old green snake to the new new blue and yellow snakes. - -- Issue #17721: Remove non-functional configuration dialog help button until we - make it actually gives some help when clicked. Patch by Guilherme Sim?es. - - Issue #17390: Add Python version to Idle editor window title bar. Original patches by Edmond Burnett and Kent Johnson. @@ -358,13 +405,6 @@ Tests ----- -- Issue #20532: Tests which use _testcapi are now marked as CPython only. - -- Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. - -- Issue #19990: Added tests for the imghdr module. Based on patch by - Claudiu Popa. - - Issue #19804: The test_find_mac test in test_uuid is now skipped if the ifconfig executable is not available. @@ -410,14 +450,9 @@ - Issue #19085: Added basic tests for all tkinter widget options. -- Issue #20474: Fix test_socket "unexpected success" failures on OS X 10.7+. - Documentation ------------- -- Issue #20488: Importlib is no longer *an* implementation of import, it's *the* - implementation. - - Issue #20265: Updated some parts of the Using Windows document. - Issue #20266: Updated some parts of the Windows FAQ. diff --git a/Misc/RPM/python-3.3.spec b/Misc/RPM/python-3.3.spec --- a/Misc/RPM/python-3.3.spec +++ b/Misc/RPM/python-3.3.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.3.3 +%define version 3.3.4 %define libvers 3.3 #--end constants-- %define release 1pydotorg diff --git a/README b/README --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 3.3.3 +This is Python version 3.3.4 ============================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, diff --git a/Tools/hg/hgtouch.py b/Tools/hg/hgtouch.py --- a/Tools/hg/hgtouch.py +++ b/Tools/hg/hgtouch.py @@ -36,12 +36,16 @@ result[o] = inputs return result -def check_rule(ui, repo, modified, output, inputs): +def check_rule(ui, repo, modified, basedir, output, inputs): """Verify that the output is newer than any of the inputs. Return (status, stamp), where status is True if the update succeeded, and stamp is the newest time stamp assigned to any file (might be in - the future).""" - f_output = repo.wjoin(output) + the future). + + If basedir is nonempty, it gives a directory in which the tree is to + be checked. + """ + f_output = repo.wjoin(os.path.join(basedir, output)) try: o_time = os.stat(f_output).st_mtime except OSError: @@ -51,7 +55,7 @@ backdate = None backdate_source = None for i in inputs: - f_i = repo.wjoin(i) + f_i = repo.wjoin(os.path.join(basedir, i)) try: i_time = os.stat(f_i).st_mtime except OSError: @@ -79,8 +83,14 @@ # Nothing to update return True, 0 -def do_touch(ui, repo): - modified = repo.status()[0] +def do_touch(ui, repo, basedir): + if basedir: + if not os.path.isdir(repo.wjoin(basedir)): + ui.warn("Abort: basedir %r does not exist\n" % basedir) + return + modified = [] + else: + modified = repo.status()[0] dependencies = parse_config(repo) success = True tstamp = 0 # newest time stamp assigned @@ -93,8 +103,8 @@ if i in dependencies: hold_back[output] = inputs continue - _success, _tstamp = check_rule(ui, repo, modified, output, inputs) - sucess = success and _success + _success, _tstamp = check_rule(ui, repo, modified, basedir, output, inputs) + success = success and _success tstamp = max(tstamp, _tstamp) # put back held back rules dependencies.update(hold_back) @@ -109,11 +119,12 @@ return False return success -def touch(ui, repo): +def touch(ui, repo, basedir): "touch generated files that are older than their sources after an update." - do_touch(ui, repo) + do_touch(ui, repo, basedir) cmdtable = { - "touch": (touch, [], - "touch generated files according to the .hgtouch configuration") + "touch": (touch, + [('b', 'basedir', '', 'base dir of the tree to apply touching', 'BASEDIR')], + "hg touch [-b BASEDIR]") } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:05:16 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:05:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Fix_trailing_w?= =?utf-8?q?hitespace=2E?= Message-ID: <3fNKQ465TCz7LkS@mail.python.org> http://hg.python.org/cpython/rev/3c81185210da changeset: 89122:3c81185210da branch: 3.3 user: Georg Brandl date: Mon Feb 10 22:05:16 2014 +0100 summary: Fix trailing whitespace. files: Lib/idlelib/NEWS.txt | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,7 +3,7 @@ - Issue #17390: Add Python version to Idle editor window title bar. Original patches by Edmond Burnett and Kent Johnson. - + - Issue #18960: IDLE now ignores the source encoding declaration on the second line if the first line contains anything except a comment. @@ -939,4 +939,3 @@ -------------------------------------------------------------------- Refer to HISTORY.txt for additional information on earlier releases. -------------------------------------------------------------------- - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:11:03 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 10 Feb 2014 22:11:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge_with_3=2E3?= Message-ID: <3fNKXl2vyQz7LjM@mail.python.org> http://hg.python.org/cpython/rev/318de3affa3d changeset: 89123:318de3affa3d parent: 89103:20dc8d6430eb parent: 89122:3c81185210da user: Georg Brandl date: Mon Feb 10 22:11:21 2014 +0100 summary: merge with 3.3 files: .hgtags | 2 + Doc/tools/sphinxext/susp-ignored.csv | 1 + Lib/idlelib/NEWS.txt | 1 - Lib/smtplib.py | 5 ++- Lib/test/mock_socket.py | 9 +++- Lib/test/test_smtplib.py | 30 +++++++++++++++- 6 files changed, 43 insertions(+), 5 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -118,6 +118,8 @@ fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 +fa92f5f940c6c0d839d7f0611e4b717606504a3c v3.3.4rc1 +7ff62415e4263c432c8acf6e424224209211eadb v3.3.4 46535f65e7f3bcdcf176f36d34bc1fed719ffd2b v3.4.0a1 9265a2168e2cb2a84785d8717792acc661e6b692 v3.4.0a2 dd9cdf90a5073510877e9dd5112f8e6cf20d5e89 v3.4.0a3 diff --git a/Doc/tools/sphinxext/susp-ignored.csv b/Doc/tools/sphinxext/susp-ignored.csv --- a/Doc/tools/sphinxext/susp-ignored.csv +++ b/Doc/tools/sphinxext/susp-ignored.csv @@ -282,3 +282,4 @@ whatsnew/changelog,,::,": Fix FTP tests for IPv6, bind to ""::1"" instead of ""localhost""." whatsnew/changelog,,::,": Use ""127.0.0.1"" or ""::1"" instead of ""localhost"" as much as" whatsnew/changelog,,:password,user:password +whatsnew/changelog,,:gz,w:gz diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -875,4 +875,3 @@ -------------------------------------------------------------------- Refer to HISTORY.txt for additional information on earlier releases. -------------------------------------------------------------------- - diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -62,6 +62,7 @@ SMTP_SSL_PORT = 465 CRLF = "\r\n" bCRLF = b"\r\n" +_MAXLINE = 8192 # more than 8 times larger than RFC 821, 4.5.3 OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) @@ -365,7 +366,7 @@ self.file = self.sock.makefile('rb') while 1: try: - line = self.file.readline() + line = self.file.readline(_MAXLINE + 1) except OSError as e: self.close() raise SMTPServerDisconnected("Connection unexpectedly closed: " @@ -375,6 +376,8 @@ raise SMTPServerDisconnected("Connection unexpectedly closed") if self.debuglevel > 0: print('reply:', repr(line), file=stderr) + if len(line) > _MAXLINE: + raise SMTPResponseException(500, "Line too long.") resp.append(line[4:].strip(b' \t\r\n')) code = line[:3] # Check that the error code is syntactically correct. diff --git a/Lib/test/mock_socket.py b/Lib/test/mock_socket.py --- a/Lib/test/mock_socket.py +++ b/Lib/test/mock_socket.py @@ -21,8 +21,13 @@ """ def __init__(self, lines): self.lines = lines - def readline(self): - return self.lines.pop(0) + b'\r\n' + def readline(self, limit=-1): + result = self.lines.pop(0) + b'\r\n' + if limit >= 0: + # Re-insert the line, removing the \r\n we added. + self.lines.insert(0, result[limit:-2]) + result = result[:limit] + return result def close(self): pass diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -563,6 +563,33 @@ HOST, self.port, 'localhost', 3) + at unittest.skipUnless(threading, 'Threading required for this test.') +class TooLongLineTests(unittest.TestCase): + respdata = b'250 OK' + (b'.' * smtplib._MAXLINE * 2) + b'\n' + + def setUp(self): + self.old_stdout = sys.stdout + self.output = io.StringIO() + sys.stdout = self.output + + self.evt = threading.Event() + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.settimeout(15) + self.port = support.bind_port(self.sock) + servargs = (self.evt, self.respdata, self.sock) + threading.Thread(target=server, args=servargs).start() + self.evt.wait() + self.evt.clear() + + def tearDown(self): + self.evt.wait() + sys.stdout = self.old_stdout + + def testLineTooLong(self): + self.assertRaises(smtplib.SMTPResponseException, smtplib.SMTP, + HOST, self.port, 'localhost', 3) + + sim_users = {'Mr.A at somewhere.com':'John A', 'Ms.B at xn--fo-fka.com':'Sally B', 'Mrs.C at somewhereesle.com':'Ruth C', @@ -888,7 +915,8 @@ def test_main(verbose=None): support.run_unittest(GeneralTests, DebuggingServerTests, NonConnectingTests, - BadHELOServerTests, SMTPSimTests) + BadHELOServerTests, SMTPSimTests, + TooLongLineTests) if __name__ == '__main__': test_main() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 22:47:05 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 10 Feb 2014 22:47:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320167=3A_Add_miss?= =?utf-8?q?ing_else=3A_break_in_3_places_as_noticed_by_Serhiy=2E?= Message-ID: <3fNLLK3tbmz7LjW@mail.python.org> http://hg.python.org/cpython/rev/b9e124851e47 changeset: 89124:b9e124851e47 user: Terry Jan Reedy date: Mon Feb 10 16:46:28 2014 -0500 summary: Issue #20167: Add missing else: break in 3 places as noticed by Serhiy. files: Lib/idlelib/MultiCall.py | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Lib/idlelib/MultiCall.py b/Lib/idlelib/MultiCall.py --- a/Lib/idlelib/MultiCall.py +++ b/Lib/idlelib/MultiCall.py @@ -111,6 +111,8 @@ except tkinter.TclError as e: if e.args[0] == APPLICATION_GONE: pass + else: + raise # An int in range(1 << len(_modifiers)) represents a combination of modifiers # (if the least significent bit is on, _modifiers[0] is on, and so on). @@ -244,6 +246,8 @@ except tkinter.TclError as e: if e.args[0] == APPLICATION_GONE: break + else: + raise # define the list of event types to be handled by MultiEvent. the order is # compatible with the definition of event type constants. @@ -411,6 +415,8 @@ except tkinter.TclError as e: if e.args[0] == APPLICATION_GONE: break + else: + raise _multicall_dict[widget] = MultiCall return MultiCall -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 10 23:18:34 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 10 Feb 2014 23:18:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_a_couple_of_broken_links_?= =?utf-8?q?in_PEP_462=2E?= Message-ID: <3fNM2f2qKsz7LjV@mail.python.org> http://hg.python.org/peps/rev/e2c89227084e changeset: 5370:e2c89227084e user: Ezio Melotti date: Tue Feb 11 00:18:25 2014 +0200 summary: Fix a couple of broken links in PEP 462. files: pep-0462.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0462.txt b/pep-0462.txt --- a/pep-0462.txt +++ b/pep-0462.txt @@ -193,7 +193,7 @@ it easier to adapt to alternate code review systems, issue trackers and CI systems. James Blair of the OpenStack infrastructure team provided an `excellent overview of Zuul -`__ at linux.conf.au 2014. +`__ at linux.conf.au 2014. While Zuul handles several workflows for OpenStack, the specific one of interest for this PEP is the "merge gating" workflow. @@ -225,7 +225,7 @@ directly address several of the issues described in the Rationale above. .. _Zuul: http://ci.openstack.org/zuul/ -.. _Elastic recheck: http://status.openstack.org/elastic-recheck/> +.. _Elastic recheck: http://status.openstack.org/elastic-recheck/ Deferred Proposals -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Feb 10 23:43:18 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 10 Feb 2014 23:43:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320505=3A_BaseEven?= =?utf-8?q?tLoop_uses_again_the_resolution_of_the_clock_to_decide_if?= Message-ID: <3fNMbB3D15z7LjM@mail.python.org> http://hg.python.org/cpython/rev/6b850722849e changeset: 89125:6b850722849e user: Victor Stinner date: Mon Feb 10 23:42:32 2014 +0100 summary: Issue #20505: BaseEventLoop uses again the resolution of the clock to decide if scheduled tasks should be executed or not. files: Lib/asyncio/base_events.py | 5 +++-- Lib/test/test_asyncio/test_events.py | 12 ++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -96,6 +96,7 @@ self._default_executor = None self._internal_fds = 0 self._running = False + self._clock_resolution = time.get_clock_info('monotonic').resolution def _make_socket_transport(self, sock, protocol, waiter=None, *, extra=None, server=None): @@ -643,10 +644,10 @@ self._process_events(event_list) # Handle 'later' callbacks that are ready. - now = self.time() + end_time = self.time() + self._clock_resolution while self._scheduled: handle = self._scheduled[0] - if handle._when > now: + if handle._when >= end_time: break handle = heapq.heappop(self._scheduled) self._ready.append(handle) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1178,15 +1178,15 @@ 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) self.loop.run_until_complete(wait()) - # The ideal number of call is 10, but on some platforms, the selector + # The ideal number of call is 12, but on some platforms, the selector # may sleep at little bit less than timeout depending on the resolution - # of the clock used by the kernel. Tolerate 5 useless calls on these - # platforms. - self.assertLessEqual(self.loop._run_once_counter, 15, - {'time_info': time.get_clock_info('time'), - 'monotonic_info': time.get_clock_info('monotonic'), + # of the clock used by the kernel. Tolerate a few useless calls on + # these platforms. + self.assertLessEqual(self.loop._run_once_counter, 20, + {'clock_resolution': self.loop._clock_resolution, 'selector': self.loop._selector.__class__.__name__}) -- Repository URL: http://hg.python.org/cpython From tjreedy at udel.edu Mon Feb 10 22:52:40 2014 From: tjreedy at udel.edu (Terry Reedy) Date: Mon, 10 Feb 2014 16:52:40 -0500 Subject: [Python-checkins] cpython: Issue #20167: Add missing else: break in 3 places as noticed by Serhiy. In-Reply-To: <3fNLLK3tbmz7LjW@mail.python.org> References: <3fNLLK3tbmz7LjW@mail.python.org> Message-ID: <52F94A28.3030101@udel.edu> On 2/10/2014 4:47 PM, terry.reedy wrote: > http://hg.python.org/cpython/rev/b9e124851e47 > changeset: 89124:b9e124851e47 > user: Terry Jan Reedy > date: Mon Feb 10 16:46:28 2014 -0500 > summary: > Issue #20167: Add missing else: break in 3 places as noticed by Serhiy. Else: raise, as in the patch itself. From python-checkins at python.org Tue Feb 11 01:13:07 2014 From: python-checkins at python.org (r.david.murray) Date: Tue, 11 Feb 2014 01:13:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_bytes/bytearra?= =?utf-8?q?y=2Ejoin_args=2C_PYTHONPATH=3D_is_same_as_not_set=2E?= Message-ID: <3fNPZq4GKRz7LjM@mail.python.org> http://hg.python.org/cpython/rev/19568ebd5f5a changeset: 89126:19568ebd5f5a user: R David Murray date: Mon Feb 10 19:12:52 2014 -0500 summary: whatsnew: bytes/bytearray.join args, PYTHONPATH= is same as not set. files: Doc/whatsnew/3.4.rst | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -364,6 +364,9 @@ Contributed by Victor Stinner, Kang-Hao (Kenny) Lu and Serhiy Storchaka in :issue:`12892`. +* :class:`bytes`.join() and :class:`bytearray`.join() now accept arbitrary + buffer objects as arguments. (Contributed by Antoine Pitrou in + :issue:`15958`.) New Modules @@ -1609,6 +1612,20 @@ This section lists previously described changes and other bugfixes that may require changes to your code. + +Changes in 'python' command behavior +------------------------------------ + +* In a posix shell, setting an environment variable to an empty value is + generally equivalent to not setting it at all. In particular, this is true + for the :envvar:`PATH` environment variable. However, setting + :envvar:`PYTHONPATH` to an empty value was *not* equivalent to not setting it + at all: setting :envvar:`PYTHONPATH` to an empty value was equivalent to + setting it to ``.``, which leads to confusion when reasoning by analogy to + how :envvar:`PATH` works. The behavior now conforms to the normal posix + convention. + + Changes in the Python API ------------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 01:17:10 2014 From: python-checkins at python.org (r.david.murray) Date: Tue, 11 Feb 2014 01:17:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_PYTHONPATH_wording=2E_?= =?utf-8?q?_It=27s_just_PATH=2C_not_=22normal_posix_convention=22=2E?= Message-ID: <3fNPgV6K5zz7LjM@mail.python.org> http://hg.python.org/cpython/rev/dbf6bcecedc7 changeset: 89127:dbf6bcecedc7 user: R David Murray date: Mon Feb 10 19:16:40 2014 -0500 summary: Fix PYTHONPATH wording. It's just PATH, not "normal posix convention". files: Doc/whatsnew/3.4.rst | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1616,14 +1616,13 @@ Changes in 'python' command behavior ------------------------------------ -* In a posix shell, setting an environment variable to an empty value is - generally equivalent to not setting it at all. In particular, this is true - for the :envvar:`PATH` environment variable. However, setting +* In a posix shell, setting the :envvar:`PATH` environment variable to + an empty value is equivalent to not setting it at all. However, setting :envvar:`PYTHONPATH` to an empty value was *not* equivalent to not setting it at all: setting :envvar:`PYTHONPATH` to an empty value was equivalent to setting it to ``.``, which leads to confusion when reasoning by analogy to - how :envvar:`PATH` works. The behavior now conforms to the normal posix - convention. + how :envvar:`PATH` works. The behavior now conforms to the posix convention + for :envvar:`PATH`. Changes in the Python API -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 03:30:59 2014 From: python-checkins at python.org (r.david.murray) Date: Tue, 11 Feb 2014 03:30:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_slice=2Eindex_?= =?utf-8?q?no_longer_accepts_negative_values_=28or_overflows=29=2E?= Message-ID: <3fNSdv2x5Gz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/463654af6349 changeset: 89128:463654af6349 user: R David Murray date: Mon Feb 10 21:30:42 2014 -0500 summary: whatsnew: slice.index no longer accepts negative values (or overflows). files: Doc/whatsnew/3.4.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1720,6 +1720,11 @@ informative :exc:`ValueError` rather than the previous more mysterious :exc:`AttributeError` (:issue:`9177`). +* :meth:`slice.indices` no longer produces an :exc:`OverflowError` for huge + values. As a consequence of this fix, :meth:`slice.indices` now raises a + :exc:`ValueError` if given a negative length; previously it returned nonsense + values (:issue:`14794`). + Changes in the C API -------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 04:41:49 2014 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 11 Feb 2014 04:41:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogZG9uJ3QgcHV0IHJ1?= =?utf-8?q?ntime_values_in_array_initializer_for_C89_compliance_=28closes_?= =?utf-8?q?=2320588=29?= Message-ID: <3fNVCd360Gz7LjM@mail.python.org> http://hg.python.org/cpython/rev/5b3bb4bda9cb changeset: 89129:5b3bb4bda9cb branch: 3.3 parent: 89122:3c81185210da user: Benjamin Peterson date: Mon Feb 10 22:19:02 2014 -0500 summary: don't put runtime values in array initializer for C89 compliance (closes #20588) files: Misc/NEWS | 2 ++ Parser/asdl_c.py | 8 ++++++-- Python/Python-ast.c | 8 ++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #20588: Make Python-ast.c C89 compliant. + - Issue #20437: Fixed 21 potential bugs when deleting objects references. - Issue #20538: UTF-7 incremental decoder produced inconsistant string when diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1150,10 +1150,14 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) { mod_ty res; - PyObject *req_type[] = {(PyObject*)Module_type, (PyObject*)Expression_type, - (PyObject*)Interactive_type}; + PyObject *req_type[3]; char *req_name[] = {"Module", "Expression", "Interactive"}; int isinstance; + + req_type[0] = (PyObject*)Module_type; + req_type[1] = (PyObject*)Expression_type; + req_type[2] = (PyObject*)Interactive_type; + assert(0 <= mode && mode <= 2); init_types(); diff --git a/Python/Python-ast.c b/Python/Python-ast.c --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -6957,10 +6957,14 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) { mod_ty res; - PyObject *req_type[] = {(PyObject*)Module_type, (PyObject*)Expression_type, - (PyObject*)Interactive_type}; + PyObject *req_type[3]; char *req_name[] = {"Module", "Expression", "Interactive"}; int isinstance; + + req_type[0] = (PyObject*)Module_type; + req_type[1] = (PyObject*)Expression_type; + req_type[2] = (PyObject*)Interactive_type; + assert(0 <= mode && mode <= 2); init_types(); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 04:41:51 2014 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 11 Feb 2014 04:41:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4zICgjMjA1ODgp?= Message-ID: <3fNVCg4QQyz7Ljf@mail.python.org> http://hg.python.org/cpython/rev/cdaf7b38bb2c changeset: 89130:cdaf7b38bb2c parent: 89128:463654af6349 parent: 89129:5b3bb4bda9cb user: Benjamin Peterson date: Mon Feb 10 22:41:40 2014 -0500 summary: merge 3.3 (#20588) files: Misc/NEWS | 2 ++ Parser/asdl_c.py | 8 ++++++-- Python/Python-ast.c | 8 ++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ - Issue #19255: The builtins module is restored to initial value before cleaning other modules. The sys and builtins modules are cleaned last. +- Issue #20588: Make Python-ast.c C89 compliant. + - Issue #20437: Fixed 22 potential bugs when deleting objects references. - Issue #20500: Displaying an exception at interpreter shutdown no longer diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1203,10 +1203,14 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) { mod_ty res; - PyObject *req_type[] = {(PyObject*)Module_type, (PyObject*)Expression_type, - (PyObject*)Interactive_type}; + PyObject *req_type[3]; char *req_name[] = {"Module", "Expression", "Interactive"}; int isinstance; + + req_type[0] = (PyObject*)Module_type; + req_type[1] = (PyObject*)Expression_type; + req_type[2] = (PyObject*)Interactive_type; + assert(0 <= mode && mode <= 2); if (!init_types()) diff --git a/Python/Python-ast.c b/Python/Python-ast.c --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -7023,10 +7023,14 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) { mod_ty res; - PyObject *req_type[] = {(PyObject*)Module_type, (PyObject*)Expression_type, - (PyObject*)Interactive_type}; + PyObject *req_type[3]; char *req_name[] = {"Module", "Expression", "Interactive"}; int isinstance; + + req_type[0] = (PyObject*)Module_type; + req_type[1] = (PyObject*)Expression_type; + req_type[2] = (PyObject*)Interactive_type; + assert(0 <= mode && mode <= 2); if (!init_types()) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:04:34 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 11 Feb 2014 09:04:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320505=3A_Fix_Test?= =?utf-8?q?Loop=2C_set_the_clock_resolution?= Message-ID: <3fNc2p2gFKz7LjN@mail.python.org> http://hg.python.org/cpython/rev/75881b85695f changeset: 89131:75881b85695f user: Victor Stinner date: Tue Feb 11 09:03:47 2014 +0100 summary: Issue #20505: Fix TestLoop, set the clock resolution files: Lib/asyncio/test_utils.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -191,6 +191,7 @@ self._gen = gen() next(self._gen) self._time = 0 + self._clock_resolution = 1e-9 self._timers = [] self._selector = TestSelector() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:16:35 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Feb 2014 09:16:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Python_3=2E4=2E0rc1_releas?= =?utf-8?q?e=3A_Updated_pydoc_topics=2C_fixed_suspicious_markup_errors=2E?= Message-ID: <3fNcJg5QFpz7LjM@mail.python.org> http://hg.python.org/cpython/rev/fe98f131468b changeset: 89132:fe98f131468b parent: 89096:6343bdbb7085 user: Larry Hastings date: Mon Feb 10 04:26:10 2014 -0800 summary: Python 3.4.0rc1 release: Updated pydoc topics, fixed suspicious markup errors. files: Doc/library/asyncio-eventloop.rst | 2 +- Doc/library/enum.rst | 4 ++-- Doc/library/unittest.rst | 14 +++++++------- Doc/whatsnew/3.4.rst | 2 +- Lib/pydoc_data/topics.py | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -77,7 +77,7 @@ Create and return a new event loop object according to this policy's rules. If there's need to set this loop as the event loop of the current context, - :meth`set_event_loop` must be called explicitly. + :meth:`set_event_loop` must be called explicitly. Access to the global loop policy -------------------------------- diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -30,7 +30,7 @@ .. class:: Enum Base class for creating enumerated constants. See section - :ref:`Functional API` for an alternate construction syntax. + `Functional API`_ for an alternate construction syntax. .. class:: IntEnum @@ -421,7 +421,7 @@ >>> Animals = Enum('Animals', 'ant bee cat dog', module=__name__) The new pickle protocol 4 also, in some circumstances, relies on -:attr:``__qualname__`` being set to the location where pickle will be able +:attr:`__qualname__` being set to the location where pickle will be able to find the class. For example, if the class was made available in class SomeData in the global scope:: diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1917,13 +1917,13 @@ By default this runner shows :exc:`DeprecationWarning`, :exc:`PendingDeprecationWarning`, :exc:`ResourceWarning` and - :exc:`ImportWarning` even if they are :ref:`ignored by default `. Deprecation warnings caused by :ref:`deprecated unittest methods - ` are also special-cased and, when the warning filters - are ``'default'`` or ``'always'``, they will appear only once per-module, in - order to avoid too many warning messages. This behavior can be overridden - using the :option:`-Wd` or :option:`-Wa` options and leaving *warnings* to - ``None``. + :exc:`ImportWarning` even if they are :ref:`ignored by default + `. Deprecation warnings caused by :ref:`deprecated unittest + methods ` are also special-cased and, when the warning + filters are ``'default'`` or ``'always'``, they will appear only once + per-module, in order to avoid too many warning messages. This behavior can + be overridden using the :option:`-Wd` or :option:`-Wa` options and leaving + *warnings* to ``None``. .. versionchanged:: 3.2 Added the ``warnings`` argument. diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1708,7 +1708,7 @@ Changes in the C API -------------------- -* :c:func:`PyEval_EvalFrameEx`, :c:func:`PyObject_Repr(), and +* :c:func:`PyEval_EvalFrameEx`, :c:func:`PyObject_Repr`, and :c:func:`PyObject_Str`, along with some other internal C APIs, now include a debugging assertion that ensures they are not used in situations where they may silently discard a currently active exception. In cases where diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sun Jan 26 00:05:40 2014 +# Autogenerated by Sphinx on Mon Feb 10 04:20:03 2014 topics = {'assert': '\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': '\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints "[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': '\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', @@ -76,4 +76,4 @@ 'unary': '\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary "-" (minus) operator yields the negation of its numeric\nargument.\n\nThe unary "+" (plus) operator yields its numeric argument unchanged.\n\nThe unary "~" (invert) operator yields the bitwise inversion of its\ninteger argument. The bitwise inversion of "x" is defined as\n"-(x+1)". It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n"TypeError" exception is raised.\n', 'while': '\nThe "while" statement\n*********************\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n', 'with': '\nThe "with" statement\n********************\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', - 'yield': '\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nThe "yield" statement is only used when defining a generator function,\nand is only used in the body of the generator function. Using a\n"yield" statement in a function definition is sufficient to cause that\ndefinition to create a generator function instead of a normal\nfunction.\n\nWhen a generator function is called, it returns an iterator known as a\ngenerator iterator, or more commonly, a generator. The body of the\ngenerator function is executed by calling the "next()" function on the\ngenerator repeatedly until it raises an exception.\n\nWhen a "yield" statement is executed, the state of the generator is\nfrozen and the value of "expression_list" is returned to "next()"\'s\ncaller. By "frozen" we mean that all local state is retained,\nincluding the current bindings of local variables, the instruction\npointer, and the internal evaluation stack: enough information is\nsaved so that the next time "next()" is invoked, the function can\nproceed exactly as if the "yield" statement were just another external\ncall.\n\nThe "yield" statement is allowed in the "try" clause of a "try" ...\n"finally" construct. If the generator is not resumed before it is\nfinalized (by reaching a zero reference count or by being garbage\ncollected), the generator-iterator\'s "close()" method will be called,\nallowing any pending "finally" clauses to execute.\n\nWhen "yield from " is used, it treats the supplied expression as\na subiterator, producing values from it until the underlying iterator\nis exhausted.\n\n Changed in version 3.3: Added "yield from " to delegate\n control flow to a subiterator\n\nFor full details of "yield" semantics, refer to the *Yield\nexpressions* section.\n\nSee also: **PEP 0255** - Simple Generators\n\n The proposal for adding generators and the "yield" statement to\n Python.\n\n **PEP 0342** - Coroutines via Enhanced Generators\n The proposal to enhance the API and syntax of generators, making\n them usable as simple coroutines.\n\n **PEP 0380** - Syntax for Delegating to a Subgenerator\n The proposal to introduce the "yield_from" syntax, making\n delegation to sub-generators easy.\n'} + 'yield': '\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nA "yield" statement is semantically equivalent to a *yield\nexpression*. The yield statement can be used to omit the parentheses\nthat would otherwise be required in the equivalent yield expression\nstatement. For example, the yield statements\n\n yield \n yield from \n\nare equivalent to the yield expression statements\n\n (yield )\n (yield from )\n\nYield expressions and statements are only used when defining a\n*generator* function, and are only used in the body of the generator\nfunction. Using yield in a function definition is sufficient to cause\nthat definition to create a generator function instead of a normal\nfunction.\n\nFor full details of "yield" semantics, refer to the *Yield\nexpressions* section.\n'} -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:16:37 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Feb 2014 09:16:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_PyType=5FGetSlot_to_py?= =?utf-8?q?thon3_def_file=2E__Patch_courtesy_Martin_v=2E_L=C3=B6wis=2E?= Message-ID: <3fNcJj06qwz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/01d53ed4a98d changeset: 89133:01d53ed4a98d user: Larry Hastings date: Mon Feb 10 14:40:04 2014 -0800 summary: Add PyType_GetSlot to python3 def file. Patch courtesy Martin v. L?wis. files: PC/python3.def | 1 + PC/python34stub.def | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/PC/python3.def b/PC/python3.def --- a/PC/python3.def +++ b/PC/python3.def @@ -519,6 +519,7 @@ PyType_GenericAlloc=python34.PyType_GenericAlloc PyType_GenericNew=python34.PyType_GenericNew PyType_GetFlags=python34.PyType_GetFlags + PyType_GetSlot=python34.PyType_GetSlot PyType_IsSubtype=python34.PyType_IsSubtype PyType_Modified=python34.PyType_Modified PyType_Ready=python34.PyType_Ready diff --git a/PC/python34stub.def b/PC/python34stub.def --- a/PC/python34stub.def +++ b/PC/python34stub.def @@ -518,6 +518,7 @@ PyType_GenericAlloc PyType_GenericNew PyType_GetFlags +PyType_GetSlot PyType_IsSubtype PyType_Modified PyType_Ready -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:16:38 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Feb 2014 09:16:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Python_3=2E4=2E0rc1=3A_Ver?= =?utf-8?q?sion_bump=2E?= Message-ID: <3fNcJk1vwcz7LjT@mail.python.org> http://hg.python.org/cpython/rev/5e088cea8660 changeset: 89134:5e088cea8660 tag: v3.4.0rc1 user: Larry Hastings date: Mon Feb 10 14:45:05 2014 -0800 summary: Python 3.4.0rc1: Version bump. files: Include/patchlevel.h | 6 +++--- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 2 +- Misc/RPM/python-3.4.spec | 2 +- README | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -19,11 +19,11 @@ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 4 #define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 3 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.4.0b3+" +#define PY_VERSION "3.4.0rc1" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.4.0b3" +__version__ = "3.4.0rc1" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.4.0b3" +IDLE_VERSION = "3.4.0rc1" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,7 +5,7 @@ What's New in Python 3.4.0 release candidate 1? =============================================== -Release date: 2014-02-09 +Release date: 2014-02-10 Core and Builtins ----------------- diff --git a/Misc/RPM/python-3.4.spec b/Misc/RPM/python-3.4.spec --- a/Misc/RPM/python-3.4.spec +++ b/Misc/RPM/python-3.4.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.4.0b3 +%define version 3.4.0rc1 %define libvers 3.4 #--end constants-- %define release 1pydotorg diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.4.0 beta 3 -=================================== +This is Python version 3.4.0 release candidate 1 +================================================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Python Software Foundation. All rights reserved. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:16:39 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Feb 2014 09:16:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Added_tag_v3=2E4=2E0rc1_fo?= =?utf-8?q?r_changeset_5e088cea8660?= Message-ID: <3fNcJl3jTMz7Lk5@mail.python.org> http://hg.python.org/cpython/rev/193257a64204 changeset: 89135:193257a64204 user: Larry Hastings date: Mon Feb 10 14:45:14 2014 -0800 summary: Added tag v3.4.0rc1 for changeset 5e088cea8660 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -125,3 +125,4 @@ 3405dc9a6afaa0a06dd1f6f182ec5c998dce6f5f v3.4.0b1 ba32913eb13ec545a46dd0ce18035b6c416f0d78 v3.4.0b2 a97ce3ecc96af79bd2e1ac66ce48d9138e0ca749 v3.4.0b3 +5e088cea8660677969113741c1313d570d977e02 v3.4.0rc1 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:16:40 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Feb 2014 09:16:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Python_3=2E4=2E0rc1=3A_Pos?= =?utf-8?q?t-release_updates=2E?= Message-ID: <3fNcJm5g0cz7Lk5@mail.python.org> http://hg.python.org/cpython/rev/e64ae8b82672 changeset: 89136:e64ae8b82672 user: Larry Hastings date: Tue Feb 11 00:14:16 2014 -0800 summary: Python 3.4.0rc1: Post-release updates. files: Include/patchlevel.h | 2 +- Misc/NEWS | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.4.0rc1" +#define PY_VERSION "3.4.0rc1+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.4.0 release candidate 2? +=============================================== + +Release date: 2014-02-23 + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.4.0 release candidate 1? =============================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:16:42 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Feb 2014 09:16:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_Python_3=2E4=2E0rc1_release_branch=2E?= Message-ID: <3fNcJp2w98z7Ljd@mail.python.org> http://hg.python.org/cpython/rev/45c71f7388be changeset: 89137:45c71f7388be parent: 89136:e64ae8b82672 parent: 89131:75881b85695f user: Larry Hastings date: Tue Feb 11 00:15:46 2014 -0800 summary: Merge Python 3.4.0rc1 release branch. files: .hgtags | 2 + Doc/tools/sphinxext/susp-ignored.csv | 1 + Doc/whatsnew/3.4.rst | 21 ++++ Include/moduleobject.h | 1 + Include/pystate.h | 2 +- Lib/asyncio/base_events.py | 5 +- Lib/asyncio/test_utils.py | 1 + Lib/idlelib/MultiCall.py | 6 + Lib/idlelib/NEWS.txt | 1 - Lib/smtplib.py | 5 +- Lib/subprocess.py | 13 +- Lib/test/mock_socket.py | 9 +- Lib/test/test_asyncio/test_events.py | 14 +- Lib/test/test_builtin.py | 29 +++++ Lib/test/test_io.py | 3 +- Lib/test/test_smtplib.py | 30 +++++- Misc/NEWS | 5 + Objects/moduleobject.c | 13 +- Parser/asdl_c.py | 8 +- Python/Python-ast.c | 8 +- Python/import.c | 83 +++++++++------ Python/pystate.c | 2 + 22 files changed, 198 insertions(+), 64 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -118,6 +118,8 @@ fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 +fa92f5f940c6c0d839d7f0611e4b717606504a3c v3.3.4rc1 +7ff62415e4263c432c8acf6e424224209211eadb v3.3.4 46535f65e7f3bcdcf176f36d34bc1fed719ffd2b v3.4.0a1 9265a2168e2cb2a84785d8717792acc661e6b692 v3.4.0a2 dd9cdf90a5073510877e9dd5112f8e6cf20d5e89 v3.4.0a3 diff --git a/Doc/tools/sphinxext/susp-ignored.csv b/Doc/tools/sphinxext/susp-ignored.csv --- a/Doc/tools/sphinxext/susp-ignored.csv +++ b/Doc/tools/sphinxext/susp-ignored.csv @@ -282,3 +282,4 @@ whatsnew/changelog,,::,": Fix FTP tests for IPv6, bind to ""::1"" instead of ""localhost""." whatsnew/changelog,,::,": Use ""127.0.0.1"" or ""::1"" instead of ""localhost"" as much as" whatsnew/changelog,,:password,user:password +whatsnew/changelog,,:gz,w:gz diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -364,6 +364,9 @@ Contributed by Victor Stinner, Kang-Hao (Kenny) Lu and Serhiy Storchaka in :issue:`12892`. +* :class:`bytes`.join() and :class:`bytearray`.join() now accept arbitrary + buffer objects as arguments. (Contributed by Antoine Pitrou in + :issue:`15958`.) New Modules @@ -1609,6 +1612,19 @@ This section lists previously described changes and other bugfixes that may require changes to your code. + +Changes in 'python' command behavior +------------------------------------ + +* In a posix shell, setting the :envvar:`PATH` environment variable to + an empty value is equivalent to not setting it at all. However, setting + :envvar:`PYTHONPATH` to an empty value was *not* equivalent to not setting it + at all: setting :envvar:`PYTHONPATH` to an empty value was equivalent to + setting it to ``.``, which leads to confusion when reasoning by analogy to + how :envvar:`PATH` works. The behavior now conforms to the posix convention + for :envvar:`PATH`. + + Changes in the Python API ------------------------- @@ -1704,6 +1720,11 @@ informative :exc:`ValueError` rather than the previous more mysterious :exc:`AttributeError` (:issue:`9177`). +* :meth:`slice.indices` no longer produces an :exc:`OverflowError` for huge + values. As a consequence of this fix, :meth:`slice.indices` now raises a + :exc:`ValueError` if given a negative length; previously it returned nonsense + values (:issue:`14794`). + Changes in the C API -------------------- diff --git a/Include/moduleobject.h b/Include/moduleobject.h --- a/Include/moduleobject.h +++ b/Include/moduleobject.h @@ -25,6 +25,7 @@ PyAPI_FUNC(PyObject *) PyModule_GetFilenameObject(PyObject *); #ifndef Py_LIMITED_API PyAPI_FUNC(void) _PyModule_Clear(PyObject *); +PyAPI_FUNC(void) _PyModule_ClearDict(PyObject *); #endif PyAPI_FUNC(struct PyModuleDef*) PyModule_GetDef(PyObject*); PyAPI_FUNC(void*) PyModule_GetState(PyObject*); diff --git a/Include/pystate.h b/Include/pystate.h --- a/Include/pystate.h +++ b/Include/pystate.h @@ -33,7 +33,6 @@ int codecs_initialized; int fscodec_initialized; - #ifdef HAVE_DLOPEN int dlopenflags; #endif @@ -41,6 +40,7 @@ int tscdump; #endif + PyObject *builtins_copy; } PyInterpreterState; #endif diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -96,6 +96,7 @@ self._default_executor = None self._internal_fds = 0 self._running = False + self._clock_resolution = time.get_clock_info('monotonic').resolution def _make_socket_transport(self, sock, protocol, waiter=None, *, extra=None, server=None): @@ -643,10 +644,10 @@ self._process_events(event_list) # Handle 'later' callbacks that are ready. - now = self.time() + end_time = self.time() + self._clock_resolution while self._scheduled: handle = self._scheduled[0] - if handle._when > now: + if handle._when >= end_time: break handle = heapq.heappop(self._scheduled) self._ready.append(handle) diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -191,6 +191,7 @@ self._gen = gen() next(self._gen) self._time = 0 + self._clock_resolution = 1e-9 self._timers = [] self._selector = TestSelector() diff --git a/Lib/idlelib/MultiCall.py b/Lib/idlelib/MultiCall.py --- a/Lib/idlelib/MultiCall.py +++ b/Lib/idlelib/MultiCall.py @@ -111,6 +111,8 @@ except tkinter.TclError as e: if e.args[0] == APPLICATION_GONE: pass + else: + raise # An int in range(1 << len(_modifiers)) represents a combination of modifiers # (if the least significent bit is on, _modifiers[0] is on, and so on). @@ -244,6 +246,8 @@ except tkinter.TclError as e: if e.args[0] == APPLICATION_GONE: break + else: + raise # define the list of event types to be handled by MultiEvent. the order is # compatible with the definition of event type constants. @@ -411,6 +415,8 @@ except tkinter.TclError as e: if e.args[0] == APPLICATION_GONE: break + else: + raise _multicall_dict[widget] = MultiCall return MultiCall diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -875,4 +875,3 @@ -------------------------------------------------------------------- Refer to HISTORY.txt for additional information on earlier releases. -------------------------------------------------------------------- - diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -62,6 +62,7 @@ SMTP_SSL_PORT = 465 CRLF = "\r\n" bCRLF = b"\r\n" +_MAXLINE = 8192 # more than 8 times larger than RFC 821, 4.5.3 OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) @@ -365,7 +366,7 @@ self.file = self.sock.makefile('rb') while 1: try: - line = self.file.readline() + line = self.file.readline(_MAXLINE + 1) except OSError as e: self.close() raise SMTPServerDisconnected("Connection unexpectedly closed: " @@ -375,6 +376,8 @@ raise SMTPServerDisconnected("Connection unexpectedly closed") if self.debuglevel > 0: print('reply:', repr(line), file=stderr) + if len(line) > _MAXLINE: + raise SMTPResponseException(500, "Line too long.") resp.append(line[4:].strip(b' \t\r\n')) code = line[:3] # Check that the error code is syntactically correct. diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -738,6 +738,9 @@ class Popen(object): + + _child_created = False # Set here since __del__ checks it + def __init__(self, args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS, @@ -748,7 +751,6 @@ """Create new Popen instance.""" _cleanup() - self._child_created = False self._input = None self._communication_started = False if bufsize is None: @@ -890,11 +892,8 @@ # Wait for the process to terminate, to avoid zombies. self.wait() - def __del__(self, _maxsize=sys.maxsize, _active=_active): - # If __init__ hasn't had a chance to execute (e.g. if it - # was passed an undeclared keyword argument), we don't - # have a _child_created attribute at all. - if not getattr(self, '_child_created', False): + def __del__(self, _maxsize=sys.maxsize): + if not self._child_created: # We didn't get to successfully create a child process. return # In case the child hasn't been waited on, check if it's done. @@ -1446,7 +1445,7 @@ _WTERMSIG=os.WTERMSIG, _WIFEXITED=os.WIFEXITED, _WEXITSTATUS=os.WEXITSTATUS): # This method is called (indirectly) by __del__, so it cannot - # refer to anything outside of its local scope.""" + # refer to anything outside of its local scope. if _WIFSIGNALED(sts): self.returncode = -_WTERMSIG(sts) elif _WIFEXITED(sts): diff --git a/Lib/test/mock_socket.py b/Lib/test/mock_socket.py --- a/Lib/test/mock_socket.py +++ b/Lib/test/mock_socket.py @@ -21,8 +21,13 @@ """ def __init__(self, lines): self.lines = lines - def readline(self): - return self.lines.pop(0) + b'\r\n' + def readline(self, limit=-1): + result = self.lines.pop(0) + b'\r\n' + if limit >= 0: + # Re-insert the line, removing the \r\n we added. + self.lines.insert(0, result[limit:-2]) + result = result[:limit] + return result def close(self): pass diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1176,15 +1176,17 @@ 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) self.loop.run_until_complete(wait()) - # The ideal number of call is 6, but on some platforms, the selector + # The ideal number of call is 12, but on some platforms, the selector # may sleep at little bit less than timeout depending on the resolution - # of the clock used by the kernel. Tolerate 2 useless calls on these - # platforms. - self.assertLessEqual(self.loop._run_once_counter, 8, - {'time_info': time.get_clock_info('time'), - 'monotonic_info': time.get_clock_info('monotonic'), + # of the clock used by the kernel. Tolerate a few useless calls on + # these platforms. + self.assertLessEqual(self.loop._run_once_counter, 20, + {'clock_resolution': self.loop._clock_resolution, 'selector': self.loop._selector.__class__.__name__}) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -16,6 +16,7 @@ import warnings from operator import neg from test.support import TESTFN, unlink, run_unittest, check_warnings +from test.script_helper import assert_python_ok try: import pty, signal except ImportError: @@ -1592,6 +1593,34 @@ data = 'The quick Brown fox Jumped over The lazy Dog'.split() self.assertRaises(TypeError, sorted, data, None, lambda x,y: 0) + +class ShutdownTest(unittest.TestCase): + + def test_cleanup(self): + # Issue #19255: builtins are still available at shutdown + code = """if 1: + import builtins + import sys + + class C: + def __del__(self): + print("before") + # Check that builtins still exist + len(()) + print("after") + + c = C() + # Make this module survive until builtins and sys are cleaned + builtins.here = sys.modules[__name__] + sys.here = sys.modules[__name__] + # Create a reference loop so that this module needs to go + # through a GC phase. + here = sys.modules[__name__] + """ + rc, out, err = assert_python_ok("-c", code) + self.assertEqual(["before", "after"], out.decode().splitlines()) + + def load_tests(loader, tests, pattern): from doctest import DocTestSuite tests.addTest(DocTestSuite(builtins)) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -2691,7 +2691,8 @@ class PyTextIOWrapperTest(TextIOWrapperTest): io = pyio - shutdown_error = "LookupError: unknown encoding: ascii" + #shutdown_error = "LookupError: unknown encoding: ascii" + shutdown_error = "TypeError: 'NoneType' object is not iterable" class IncrementalNewlineDecoderTest(unittest.TestCase): diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -563,6 +563,33 @@ HOST, self.port, 'localhost', 3) + at unittest.skipUnless(threading, 'Threading required for this test.') +class TooLongLineTests(unittest.TestCase): + respdata = b'250 OK' + (b'.' * smtplib._MAXLINE * 2) + b'\n' + + def setUp(self): + self.old_stdout = sys.stdout + self.output = io.StringIO() + sys.stdout = self.output + + self.evt = threading.Event() + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.settimeout(15) + self.port = support.bind_port(self.sock) + servargs = (self.evt, self.respdata, self.sock) + threading.Thread(target=server, args=servargs).start() + self.evt.wait() + self.evt.clear() + + def tearDown(self): + self.evt.wait() + sys.stdout = self.old_stdout + + def testLineTooLong(self): + self.assertRaises(smtplib.SMTPResponseException, smtplib.SMTP, + HOST, self.port, 'localhost', 3) + + sim_users = {'Mr.A at somewhere.com':'John A', 'Ms.B at xn--fo-fka.com':'Sally B', 'Mrs.C at somewhereesle.com':'Ruth C', @@ -888,7 +915,8 @@ def test_main(verbose=None): support.run_unittest(GeneralTests, DebuggingServerTests, NonConnectingTests, - BadHELOServerTests, SMTPSimTests) + BadHELOServerTests, SMTPSimTests, + TooLongLineTests) if __name__ == '__main__': test_main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,11 @@ Core and Builtins ----------------- +- Issue #19255: The builtins module is restored to initial value before + cleaning other modules. The sys and builtins modules are cleaned last. + +- Issue #20588: Make Python-ast.c C89 compliant. + - Issue #20437: Fixed 22 potential bugs when deleting objects references. - Issue #20500: Displaying an exception at interpreter shutdown no longer diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -299,6 +299,14 @@ void _PyModule_Clear(PyObject *m) { + PyObject *d = ((PyModuleObject *)m)->md_dict; + if (d != NULL) + _PyModule_ClearDict(d); +} + +void +_PyModule_ClearDict(PyObject *d) +{ /* To make the execution order of destructors for global objects a bit more predictable, we first zap all objects whose name starts with a single underscore, before we clear @@ -308,11 +316,6 @@ Py_ssize_t pos; PyObject *key, *value; - PyObject *d; - - d = ((PyModuleObject *)m)->md_dict; - if (d == NULL) - return; /* First, clear only names starting with a single underscore */ pos = 0; diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -1203,10 +1203,14 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) { mod_ty res; - PyObject *req_type[] = {(PyObject*)Module_type, (PyObject*)Expression_type, - (PyObject*)Interactive_type}; + PyObject *req_type[3]; char *req_name[] = {"Module", "Expression", "Interactive"}; int isinstance; + + req_type[0] = (PyObject*)Module_type; + req_type[1] = (PyObject*)Expression_type; + req_type[2] = (PyObject*)Interactive_type; + assert(0 <= mode && mode <= 2); if (!init_types()) diff --git a/Python/Python-ast.c b/Python/Python-ast.c --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -7023,10 +7023,14 @@ mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode) { mod_ty res; - PyObject *req_type[] = {(PyObject*)Module_type, (PyObject*)Expression_type, - (PyObject*)Interactive_type}; + PyObject *req_type[3]; char *req_name[] = {"Module", "Expression", "Interactive"}; int isinstance; + + req_type[0] = (PyObject*)Module_type; + req_type[1] = (PyObject*)Expression_type; + req_type[2] = (PyObject*)Interactive_type; + assert(0 <= mode && mode <= 2); if (!init_types()) diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -49,9 +49,13 @@ void _PyImport_Init(void) { + PyInterpreterState *interp = PyThreadState_Get()->interp; initstr = PyUnicode_InternFromString("__init__"); if (initstr == NULL) Py_FatalError("Can't initialize import variables"); + interp->builtins_copy = PyDict_Copy(interp->builtins); + if (interp->builtins_copy == NULL) + Py_FatalError("Can't backup builtins dict"); } void @@ -397,8 +401,8 @@ PyObject *key, *value, *dict; PyInterpreterState *interp = PyThreadState_GET()->interp; PyObject *modules = interp->modules; - PyObject *builtins = interp->builtins; PyObject *weaklist = NULL; + char **p; if (modules == NULL) return; /* Already done */ @@ -411,31 +415,22 @@ /* XXX Perhaps these precautions are obsolete. Who knows? */ - value = PyDict_GetItemString(modules, "builtins"); - if (value != NULL && PyModule_Check(value)) { - dict = PyModule_GetDict(value); + if (Py_VerboseFlag) + PySys_WriteStderr("# clear builtins._\n"); + PyDict_SetItemString(interp->builtins, "_", Py_None); + + for (p = sys_deletes; *p != NULL; p++) { if (Py_VerboseFlag) - PySys_WriteStderr("# clear builtins._\n"); - PyDict_SetItemString(dict, "_", Py_None); + PySys_WriteStderr("# clear sys.%s\n", *p); + PyDict_SetItemString(interp->sysdict, *p, Py_None); } - value = PyDict_GetItemString(modules, "sys"); - if (value != NULL && PyModule_Check(value)) { - char **p; - PyObject *v; - dict = PyModule_GetDict(value); - for (p = sys_deletes; *p != NULL; p++) { - if (Py_VerboseFlag) - PySys_WriteStderr("# clear sys.%s\n", *p); - PyDict_SetItemString(dict, *p, Py_None); - } - for (p = sys_files; *p != NULL; p+=2) { - if (Py_VerboseFlag) - PySys_WriteStderr("# restore sys.%s\n", *p); - v = PyDict_GetItemString(dict, *(p+1)); - if (v == NULL) - v = Py_None; - PyDict_SetItemString(dict, *p, v); - } + for (p = sys_files; *p != NULL; p+=2) { + if (Py_VerboseFlag) + PySys_WriteStderr("# restore sys.%s\n", *p); + value = PyDict_GetItemString(interp->sysdict, *(p+1)); + if (value == NULL) + value = Py_None; + PyDict_SetItemString(interp->sysdict, *p, value); } /* We prepare a list which will receive (name, weakref) tuples of @@ -473,11 +468,15 @@ /* Clear the modules dict. */ PyDict_Clear(modules); - /* Replace the interpreter's reference to builtins with an empty dict - (module globals still have a reference to the original builtins). */ - builtins = interp->builtins; - interp->builtins = PyDict_New(); - Py_DECREF(builtins); + /* Restore the original builtins dict, to ensure that any + user data gets cleared. */ + dict = PyDict_Copy(interp->builtins); + if (dict == NULL) + PyErr_Clear(); + PyDict_Clear(interp->builtins); + if (PyDict_Update(interp->builtins, interp->builtins_copy)) + PyErr_Clear(); + Py_XDECREF(dict); /* Clear module dict copies stored in the interpreter state */ _PyState_ClearModules(); /* Collect references */ @@ -488,7 +487,15 @@ /* Now, if there are any modules left alive, clear their globals to minimize potential leaks. All C extension modules actually end - up here, since they are kept alive in the interpreter state. */ + up here, since they are kept alive in the interpreter state. + + The special treatment of "builtins" here is because even + when it's not referenced as a module, its dictionary is + referenced by almost every module's __builtins__. Since + deleting a module clears its dictionary (even if there are + references left to it), we need to delete the "builtins" + module last. Likewise, we don't delete sys until the very + end because it is implicitly referenced (e.g. by print). */ if (weaklist != NULL) { Py_ssize_t i, n; n = PyList_GET_SIZE(weaklist); @@ -498,17 +505,27 @@ PyObject *mod = PyWeakref_GET_OBJECT(PyTuple_GET_ITEM(tup, 1)); if (mod == Py_None) continue; + assert(PyModule_Check(mod)); + dict = PyModule_GetDict(mod); + if (dict == interp->builtins || dict == interp->sysdict) + continue; Py_INCREF(mod); - assert(PyModule_Check(mod)); if (Py_VerboseFlag && PyUnicode_Check(name)) - PySys_FormatStderr("# cleanup[3] wiping %U\n", - name, mod); + PySys_FormatStderr("# cleanup[3] wiping %U\n", name); _PyModule_Clear(mod); Py_DECREF(mod); } Py_DECREF(weaklist); } + /* Next, delete sys and builtins (in that order) */ + if (Py_VerboseFlag) + PySys_FormatStderr("# cleanup[3] wiping sys\n"); + _PyModule_ClearDict(interp->sysdict); + if (Py_VerboseFlag) + PySys_FormatStderr("# cleanup[3] wiping builtins\n"); + _PyModule_ClearDict(interp->builtins); + /* Clear and delete the modules directory. Actual modules will still be there only if imported during the execution of some destructor. */ diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -72,6 +72,7 @@ interp->modules_by_index = NULL; interp->sysdict = NULL; interp->builtins = NULL; + interp->builtins_copy = NULL; interp->tstate_head = NULL; interp->codec_search_path = NULL; interp->codec_search_cache = NULL; @@ -115,6 +116,7 @@ Py_CLEAR(interp->modules_by_index); Py_CLEAR(interp->sysdict); Py_CLEAR(interp->builtins); + Py_CLEAR(interp->builtins_copy); Py_CLEAR(interp->importlib); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:17:30 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 11 Feb 2014 09:17:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Updated_Python_3=2E4_release_?= =?utf-8?q?PEP_with_dates_of_actual_releases=2E?= Message-ID: <3fNcKk1SS3z7Ljm@mail.python.org> http://hg.python.org/peps/rev/9bcb202e5c56 changeset: 5371:9bcb202e5c56 user: Larry Hastings date: Tue Feb 11 00:17:27 2014 -0800 summary: Updated Python 3.4 release PEP with dates of actual releases. files: pep-0429.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0429.txt b/pep-0429.txt --- a/pep-0429.txt +++ b/pep-0429.txt @@ -42,13 +42,13 @@ - 3.4.0 alpha 4: October 20, 2013 - 3.4.0 beta 1: November 24, 2013 - 3.4.0 beta 2: January 5, 2014 +- 3.4.0 beta 3: January 26, 2014 +- 3.4.0 candidate 1: February 10, 2014 (Beta 1 is also "feature freeze"--no new features beyond this point.) The anticipated schedule for future releases: -- 3.4.0 beta 3: January 26, 2014 -- 3.4.0 candidate 1: February 9, 2014 - 3.4.0 candidate 2: February 23, 2014 - 3.4.0 final: March 16, 2014 -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Tue Feb 11 09:27:29 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 11 Feb 2014 09:27:29 +0100 Subject: [Python-checkins] Daily reference leaks (dbf6bcecedc7): sum=0 Message-ID: results for dbf6bcecedc7 on branch "default" -------------------------------------------- test_site leaked [2, -2, 0] references, sum=0 test_site leaked [2, -2, 0] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogWneNez', '-x'] From python-checkins at python.org Tue Feb 11 09:41:16 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 11 Feb 2014 09:41:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE5ODU2?= =?utf-8?q?=3A_shutil=2Emove=28=29_failed_to_move_a_directory_to_other_dir?= =?utf-8?q?ectory?= Message-ID: <3fNcs823Hgz7LjN@mail.python.org> http://hg.python.org/cpython/rev/51afe7839f8a changeset: 89138:51afe7839f8a branch: 2.7 parent: 89102:3a7638baf511 user: Serhiy Storchaka date: Tue Feb 11 10:30:06 2014 +0200 summary: Issue #19856: shutil.move() failed to move a directory to other directory on Windows if source name ends with os.altsep. files: Lib/shutil.py | 3 ++- Lib/test/test_shutil.py | 9 +++++++++ Misc/NEWS | 3 +++ 3 files changed, 14 insertions(+), 1 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -259,7 +259,8 @@ def _basename(path): # A basename() variant which first strips the trailing slash, if present. # Thus we always get the last component of the path, even for directories. - return os.path.basename(path.rstrip(os.path.sep)) + sep = os.path.sep + (os.path.altsep or '') + return os.path.basename(path.rstrip(sep)) def move(src, dst): """Recursively move a file or directory to another location. This is diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -698,6 +698,15 @@ self._check_move_dir(self.src_dir, self.dir_other_fs, os.path.join(self.dir_other_fs, os.path.basename(self.src_dir))) + def test_move_dir_sep_to_dir(self): + self._check_move_dir(self.src_dir + os.path.sep, self.dst_dir, + os.path.join(self.dst_dir, os.path.basename(self.src_dir))) + + @unittest.skipUnless(os.path.altsep, 'requires os.path.altsep') + def test_move_dir_altsep_to_dir(self): + self._check_move_dir(self.src_dir + os.path.altsep, self.dst_dir, + os.path.join(self.dst_dir, os.path.basename(self.src_dir))) + def test_existing_file_inside_dest_dir(self): # A file with the same name inside the destination dir already exists. with open(self.dst_file, "wb"): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -44,6 +44,9 @@ Library ------- +- Issue #19856: shutil.move() failed to move a directory to other directory + on Windows if source name ends with os.altsep. + - Issue #14983: email.generator now always adds a line end after each MIME boundary marker, instead of doing so only when there is an epilogue. This fixes an RFC compliance bug and solves an issue with signed MIME parts. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:41:17 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 11 Feb 2014 09:41:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE5ODU2?= =?utf-8?q?=3A_shutil=2Emove=28=29_failed_to_move_a_directory_to_other_dir?= =?utf-8?q?ectory?= Message-ID: <3fNcs94Ghpz7LjS@mail.python.org> http://hg.python.org/cpython/rev/373ec8711ad0 changeset: 89139:373ec8711ad0 branch: 3.3 parent: 89129:5b3bb4bda9cb user: Serhiy Storchaka date: Tue Feb 11 10:30:59 2014 +0200 summary: Issue #19856: shutil.move() failed to move a directory to other directory on Windows if source name ends with os.altsep. files: Lib/shutil.py | 3 ++- Lib/test/test_shutil.py | 9 +++++++++ Misc/NEWS | 3 +++ 3 files changed, 14 insertions(+), 1 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -484,7 +484,8 @@ def _basename(path): # A basename() variant which first strips the trailing slash, if present. # Thus we always get the last component of the path, even for directories. - return os.path.basename(path.rstrip(os.path.sep)) + sep = os.path.sep + (os.path.altsep or '') + return os.path.basename(path.rstrip(sep)) def move(src, dst): """Recursively move a file or directory to another location. This is diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1481,6 +1481,15 @@ # Move a dir inside an existing dir on another filesystem. self.test_move_dir_to_dir() + def test_move_dir_sep_to_dir(self): + self._check_move_dir(self.src_dir + os.path.sep, self.dst_dir, + os.path.join(self.dst_dir, os.path.basename(self.src_dir))) + + @unittest.skipUnless(os.path.altsep, 'requires os.path.altsep') + def test_move_dir_altsep_to_dir(self): + self._check_move_dir(self.src_dir + os.path.altsep, self.dst_dir, + os.path.join(self.dst_dir, os.path.basename(self.src_dir))) + def test_existing_file_inside_dest_dir(self): # A file with the same name inside the destination dir already exists. with open(self.dst_file, "wb"): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -20,6 +20,9 @@ Library ------- +- Issue #19856: shutil.move() failed to move a directory to other directory + on Windows if source name ends with os.altsep. + - Issue #14983: email.generator now always adds a line end after each MIME boundary marker, instead of doing so only when there is an epilogue. This fixes an RFC compliance bug and solves an issue with signed MIME parts. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:41:18 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 11 Feb 2014 09:41:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2319856=3A_shutil=2Emove=28=29_failed_to_move_a_d?= =?utf-8?q?irectory_to_other_directory?= Message-ID: <3fNcsB6RpMz7Lk1@mail.python.org> http://hg.python.org/cpython/rev/41610ad5c755 changeset: 89140:41610ad5c755 parent: 89130:cdaf7b38bb2c parent: 89139:373ec8711ad0 user: Serhiy Storchaka date: Tue Feb 11 10:32:41 2014 +0200 summary: Issue #19856: shutil.move() failed to move a directory to other directory on Windows if source name ends with os.altsep. files: Lib/shutil.py | 3 ++- Lib/test/test_shutil.py | 9 +++++++++ Misc/NEWS | 3 +++ 3 files changed, 14 insertions(+), 1 deletions(-) diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -483,7 +483,8 @@ def _basename(path): # A basename() variant which first strips the trailing slash, if present. # Thus we always get the last component of the path, even for directories. - return os.path.basename(path.rstrip(os.path.sep)) + sep = os.path.sep + (os.path.altsep or '') + return os.path.basename(path.rstrip(sep)) def move(src, dst): """Recursively move a file or directory to another location. This is diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -1492,6 +1492,15 @@ # Move a dir inside an existing dir on another filesystem. self.test_move_dir_to_dir() + def test_move_dir_sep_to_dir(self): + self._check_move_dir(self.src_dir + os.path.sep, self.dst_dir, + os.path.join(self.dst_dir, os.path.basename(self.src_dir))) + + @unittest.skipUnless(os.path.altsep, 'requires os.path.altsep') + def test_move_dir_altsep_to_dir(self): + self._check_move_dir(self.src_dir + os.path.altsep, self.dst_dir, + os.path.join(self.dst_dir, os.path.basename(self.src_dir))) + def test_existing_file_inside_dest_dir(self): # A file with the same name inside the destination dir already exists. with open(self.dst_file, "wb"): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -37,6 +37,9 @@ Library ------- +- Issue #19856: shutil.move() failed to move a directory to other directory + on Windows if source name ends with os.altsep. + - Issue #20530: The signatures for slot builtins have been updated to reflect the fact that they only accept positional-only arguments. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 09:41:20 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 11 Feb 2014 09:41:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_heads?= Message-ID: <3fNcsD48s9z7LjV@mail.python.org> http://hg.python.org/cpython/rev/93f58fc10000 changeset: 89141:93f58fc10000 parent: 89140:41610ad5c755 parent: 89137:45c71f7388be user: Serhiy Storchaka date: Tue Feb 11 10:38:44 2014 +0200 summary: Merge heads files: .hgtags | 1 + Doc/library/asyncio-eventloop.rst | 2 +- Doc/library/enum.rst | 4 +- Doc/library/unittest.rst | 14 ++++++------ Doc/whatsnew/3.4.rst | 2 +- Include/patchlevel.h | 6 ++-- Lib/asyncio/test_utils.py | 1 + Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Lib/pydoc_data/topics.py | 4 +- Misc/NEWS | 20 +++++++++++++++--- Misc/RPM/python-3.4.spec | 2 +- PC/python3.def | 1 + PC/python34stub.def | 1 + README | 4 +- 15 files changed, 41 insertions(+), 25 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -127,3 +127,4 @@ 3405dc9a6afaa0a06dd1f6f182ec5c998dce6f5f v3.4.0b1 ba32913eb13ec545a46dd0ce18035b6c416f0d78 v3.4.0b2 a97ce3ecc96af79bd2e1ac66ce48d9138e0ca749 v3.4.0b3 +5e088cea8660677969113741c1313d570d977e02 v3.4.0rc1 diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -77,7 +77,7 @@ Create and return a new event loop object according to this policy's rules. If there's need to set this loop as the event loop of the current context, - :meth`set_event_loop` must be called explicitly. + :meth:`set_event_loop` must be called explicitly. Access to the global loop policy -------------------------------- diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -30,7 +30,7 @@ .. class:: Enum Base class for creating enumerated constants. See section - :ref:`Functional API` for an alternate construction syntax. + `Functional API`_ for an alternate construction syntax. .. class:: IntEnum @@ -421,7 +421,7 @@ >>> Animals = Enum('Animals', 'ant bee cat dog', module=__name__) The new pickle protocol 4 also, in some circumstances, relies on -:attr:``__qualname__`` being set to the location where pickle will be able +:attr:`__qualname__` being set to the location where pickle will be able to find the class. For example, if the class was made available in class SomeData in the global scope:: diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1917,13 +1917,13 @@ By default this runner shows :exc:`DeprecationWarning`, :exc:`PendingDeprecationWarning`, :exc:`ResourceWarning` and - :exc:`ImportWarning` even if they are :ref:`ignored by default `. Deprecation warnings caused by :ref:`deprecated unittest methods - ` are also special-cased and, when the warning filters - are ``'default'`` or ``'always'``, they will appear only once per-module, in - order to avoid too many warning messages. This behavior can be overridden - using the :option:`-Wd` or :option:`-Wa` options and leaving *warnings* to - ``None``. + :exc:`ImportWarning` even if they are :ref:`ignored by default + `. Deprecation warnings caused by :ref:`deprecated unittest + methods ` are also special-cased and, when the warning + filters are ``'default'`` or ``'always'``, they will appear only once + per-module, in order to avoid too many warning messages. This behavior can + be overridden using the :option:`-Wd` or :option:`-Wa` options and leaving + *warnings* to ``None``. .. versionchanged:: 3.2 Added the ``warnings`` argument. diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1729,7 +1729,7 @@ Changes in the C API -------------------- -* :c:func:`PyEval_EvalFrameEx`, :c:func:`PyObject_Repr(), and +* :c:func:`PyEval_EvalFrameEx`, :c:func:`PyObject_Repr`, and :c:func:`PyObject_Str`, along with some other internal C APIs, now include a debugging assertion that ensures they are not used in situations where they may silently discard a currently active exception. In cases where diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -19,11 +19,11 @@ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 4 #define PY_MICRO_VERSION 0 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 3 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.4.0b3+" +#define PY_VERSION "3.4.0rc1+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -191,6 +191,7 @@ self._gen = gen() next(self._gen) self._time = 0 + self._clock_resolution = 1e-9 self._timers = [] self._selector = TestSelector() diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.4.0b3" +__version__ = "3.4.0rc1" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.4.0b3" +IDLE_VERSION = "3.4.0rc1" diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sun Jan 26 00:05:40 2014 +# Autogenerated by Sphinx on Mon Feb 10 04:20:03 2014 topics = {'assert': '\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': '\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints "[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': '\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', @@ -76,4 +76,4 @@ 'unary': '\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary "-" (minus) operator yields the negation of its numeric\nargument.\n\nThe unary "+" (plus) operator yields its numeric argument unchanged.\n\nThe unary "~" (invert) operator yields the bitwise inversion of its\ninteger argument. The bitwise inversion of "x" is defined as\n"-(x+1)". It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n"TypeError" exception is raised.\n', 'while': '\nThe "while" statement\n*********************\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n', 'with': '\nThe "with" statement\n********************\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', - 'yield': '\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nThe "yield" statement is only used when defining a generator function,\nand is only used in the body of the generator function. Using a\n"yield" statement in a function definition is sufficient to cause that\ndefinition to create a generator function instead of a normal\nfunction.\n\nWhen a generator function is called, it returns an iterator known as a\ngenerator iterator, or more commonly, a generator. The body of the\ngenerator function is executed by calling the "next()" function on the\ngenerator repeatedly until it raises an exception.\n\nWhen a "yield" statement is executed, the state of the generator is\nfrozen and the value of "expression_list" is returned to "next()"\'s\ncaller. By "frozen" we mean that all local state is retained,\nincluding the current bindings of local variables, the instruction\npointer, and the internal evaluation stack: enough information is\nsaved so that the next time "next()" is invoked, the function can\nproceed exactly as if the "yield" statement were just another external\ncall.\n\nThe "yield" statement is allowed in the "try" clause of a "try" ...\n"finally" construct. If the generator is not resumed before it is\nfinalized (by reaching a zero reference count or by being garbage\ncollected), the generator-iterator\'s "close()" method will be called,\nallowing any pending "finally" clauses to execute.\n\nWhen "yield from " is used, it treats the supplied expression as\na subiterator, producing values from it until the underlying iterator\nis exhausted.\n\n Changed in version 3.3: Added "yield from " to delegate\n control flow to a subiterator\n\nFor full details of "yield" semantics, refer to the *Yield\nexpressions* section.\n\nSee also: **PEP 0255** - Simple Generators\n\n The proposal for adding generators and the "yield" statement to\n Python.\n\n **PEP 0342** - Coroutines via Enhanced Generators\n The proposal to enhance the API and syntax of generators, making\n them usable as simple coroutines.\n\n **PEP 0380** - Syntax for Delegating to a Subgenerator\n The proposal to introduce the "yield_from" syntax, making\n delegation to sub-generators easy.\n'} + 'yield': '\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nA "yield" statement is semantically equivalent to a *yield\nexpression*. The yield statement can be used to omit the parentheses\nthat would otherwise be required in the equivalent yield expression\nstatement. For example, the yield statements\n\n yield \n yield from \n\nare equivalent to the yield expression statements\n\n (yield )\n (yield from )\n\nYield expressions and statements are only used when defining a\n*generator* function, and are only used in the body of the generator\nfunction. Using yield in a function definition is sufficient to cause\nthat definition to create a generator function instead of a normal\nfunction.\n\nFor full details of "yield" semantics, refer to the *Yield\nexpressions* section.\n'} diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,10 +2,25 @@ Python News +++++++++++ +What's New in Python 3.4.0 release candidate 2? +=============================================== + +Release date: 2014-02-23 + +Core and Builtins +----------------- + +Library +------- + +- Issue #19856: shutil.move() failed to move a directory to other directory + on Windows if source name ends with os.altsep. + + What's New in Python 3.4.0 release candidate 1? =============================================== -Release date: 2014-02-09 +Release date: 2014-02-10 Core and Builtins ----------------- @@ -37,9 +52,6 @@ Library ------- -- Issue #19856: shutil.move() failed to move a directory to other directory - on Windows if source name ends with os.altsep. - - Issue #20530: The signatures for slot builtins have been updated to reflect the fact that they only accept positional-only arguments. diff --git a/Misc/RPM/python-3.4.spec b/Misc/RPM/python-3.4.spec --- a/Misc/RPM/python-3.4.spec +++ b/Misc/RPM/python-3.4.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.4.0b3 +%define version 3.4.0rc1 %define libvers 3.4 #--end constants-- %define release 1pydotorg diff --git a/PC/python3.def b/PC/python3.def --- a/PC/python3.def +++ b/PC/python3.def @@ -519,6 +519,7 @@ PyType_GenericAlloc=python34.PyType_GenericAlloc PyType_GenericNew=python34.PyType_GenericNew PyType_GetFlags=python34.PyType_GetFlags + PyType_GetSlot=python34.PyType_GetSlot PyType_IsSubtype=python34.PyType_IsSubtype PyType_Modified=python34.PyType_Modified PyType_Ready=python34.PyType_Ready diff --git a/PC/python34stub.def b/PC/python34stub.def --- a/PC/python34stub.def +++ b/PC/python34stub.def @@ -518,6 +518,7 @@ PyType_GenericAlloc PyType_GenericNew PyType_GetFlags +PyType_GetSlot PyType_IsSubtype PyType_Modified PyType_Ready diff --git a/README b/README --- a/README +++ b/README @@ -1,5 +1,5 @@ -This is Python version 3.4.0 beta 3 -=================================== +This is Python version 3.4.0 release candidate 1 +================================================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Python Software Foundation. All rights reserved. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 10:09:34 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 11 Feb 2014 10:09:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320505=3A_Improve_?= =?utf-8?q?debug_info_in_asyncio_event_loop?= Message-ID: <3fNdTp3hLZz7LjN@mail.python.org> http://hg.python.org/cpython/rev/03cb6ddc7040 changeset: 89142:03cb6ddc7040 user: Victor Stinner date: Tue Feb 11 10:08:08 2014 +0100 summary: Issue #20505: Improve debug info in asyncio event loop files: Lib/asyncio/base_events.py | 23 ++++++++++++++++++----- 1 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -634,12 +634,25 @@ else: logger.log(level, 'poll took %.3f seconds', t1-t0) else: - t0 = self.time() + t0_monotonic = time.monotonic() + t0 = time.perf_counter() event_list = self._selector.select(timeout) - dt = self.time() - t0 - if not event_list and timeout and dt < timeout: - print("asyncio: selector.select(%.3f ms) took %.3f ms" - % (timeout*1e3, dt*1e3), + dt = time.perf_counter() - t0 + dt_monotonic = time.monotonic() - t0_monotonic + if not event_list and timeout: # and dt < timeout: + selector = self._selector.__class__.__name__ + if (selector.startswith(("Poll", "Epoll", "Iocp")) + or timeout > 1e-3 or dt > 1e-3): + unit, factor = "ms", 1e3 + else: + unit, factor = "us", 1e6 + print("asyncio: %s.select(%.3f %s) took %.3f %s" + " (monotonic: %.3f %s, clock res: %.3f %s)" + % (self._selector.__class__.__name__, + timeout * factor, unit, + dt * factor, unit, + dt_monotonic * factor, unit, + self._clock_resolution * factor, unit), file=sys.__stderr__, flush=True) self._process_events(event_list) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 10:10:51 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 11 Feb 2014 10:10:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320505=3A_Oops=2C_?= =?utf-8?q?only_print_debug_info_if_selector=2Eselect=28timeout=29_took_le?= =?utf-8?q?ss?= Message-ID: <3fNdWH6N94z7LjM@mail.python.org> http://hg.python.org/cpython/rev/9c1840e8d643 changeset: 89143:9c1840e8d643 user: Victor Stinner date: Tue Feb 11 10:10:41 2014 +0100 summary: Issue #20505: Oops, only print debug info if selector.select(timeout) took less than timeout files: Lib/asyncio/base_events.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -639,7 +639,7 @@ event_list = self._selector.select(timeout) dt = time.perf_counter() - t0 dt_monotonic = time.monotonic() - t0_monotonic - if not event_list and timeout: # and dt < timeout: + if not event_list and timeout and dt < timeout: selector = self._selector.__class__.__name__ if (selector.startswith(("Poll", "Epoll", "Iocp")) or timeout > 1e-3 or dt > 1e-3): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 10:29:03 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 11 Feb 2014 10:29:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320505=3A_use_also?= =?utf-8?q?_the_monotonic_time_to_decide_if_asyncio_debug_traces?= Message-ID: <3fNdwH1TlFzLq6@mail.python.org> http://hg.python.org/cpython/rev/a631b01d1715 changeset: 89144:a631b01d1715 user: Victor Stinner date: Tue Feb 11 10:26:53 2014 +0100 summary: Issue #20505: use also the monotonic time to decide if asyncio debug traces should be printed files: Lib/asyncio/base_events.py | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -639,15 +639,16 @@ event_list = self._selector.select(timeout) dt = time.perf_counter() - t0 dt_monotonic = time.monotonic() - t0_monotonic - if not event_list and timeout and dt < timeout: + if (not event_list and timeout + and (dt < timeout or dt_monotonic < timeout)): selector = self._selector.__class__.__name__ if (selector.startswith(("Poll", "Epoll", "Iocp")) or timeout > 1e-3 or dt > 1e-3): unit, factor = "ms", 1e3 else: unit, factor = "us", 1e6 - print("asyncio: %s.select(%.3f %s) took %.3f %s" - " (monotonic: %.3f %s, clock res: %.3f %s)" + print("asyncio: %s.select(%.4f %s) took %.3f %s" + " (monotonic=%.3f %s, clock res=%.3f %s)" % (self._selector.__class__.__name__, timeout * factor, unit, dt * factor, unit, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 11:37:20 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 11 Feb 2014 11:37:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2C_Tulip_issue_126?= =?utf-8?b?OiBjYWxsX3Nvb24oKSwgY2FsbF9zb29uX3RocmVhZHNhZmUoKSwgY2FsbF9s?= =?utf-8?b?YXRlcigpLA==?= Message-ID: <3fNgR44py5z7LjN@mail.python.org> http://hg.python.org/cpython/rev/3ba4742a6fde changeset: 89145:3ba4742a6fde user: Victor Stinner date: Tue Feb 11 11:34:30 2014 +0100 summary: asyncio, Tulip issue 126: call_soon(), call_soon_threadsafe(), call_later(), call_at() and run_in_executor() now raise a TypeError if the callback is a coroutine function. files: Lib/asyncio/base_events.py | 6 +++ Lib/asyncio/test_utils.py | 5 ++- Lib/test/test_asyncio/test_base_events.py | 18 ++++++++++ Lib/test/test_asyncio/test_proactor_events.py | 2 +- Lib/test/test_asyncio/test_selector_events.py | 9 ++-- Lib/test/test_asyncio/test_tasks.py | 12 ++--- 6 files changed, 39 insertions(+), 13 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -227,6 +227,8 @@ def call_at(self, when, callback, *args): """Like call_later(), but uses an absolute time.""" + if tasks.iscoroutinefunction(callback): + raise TypeError("coroutines cannot be used with call_at()") timer = events.TimerHandle(when, callback, args) heapq.heappush(self._scheduled, timer) return timer @@ -241,6 +243,8 @@ Any positional arguments after the callback will be passed to the callback when it is called. """ + if tasks.iscoroutinefunction(callback): + raise TypeError("coroutines cannot be used with call_soon()") handle = events.Handle(callback, args) self._ready.append(handle) return handle @@ -252,6 +256,8 @@ return handle def run_in_executor(self, executor, callback, *args): + if tasks.iscoroutinefunction(callback): + raise TypeError("coroutines cannot be used with run_in_executor()") if isinstance(callback, events.Handle): assert not args assert not isinstance(callback, events.TimerHandle) diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -135,7 +135,7 @@ if name.startswith('__') and name.endswith('__'): # skip magic names continue - dct[name] = unittest.mock.Mock(return_value=None) + dct[name] = MockCallback(return_value=None) return type('TestProtocol', (base,) + base.__bases__, dct)() @@ -274,3 +274,6 @@ def _write_to_self(self): pass + +def MockCallback(**kwargs): + return unittest.mock.Mock(spec=['__call__'], **kwargs) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -567,6 +567,7 @@ m_socket.getaddrinfo.return_value = [ (2, 1, 6, '', ('127.0.0.1', 10100))] + m_socket.getaddrinfo._is_coroutine = False m_sock = m_socket.socket.return_value = unittest.mock.Mock() m_sock.bind.side_effect = Err @@ -577,6 +578,7 @@ @unittest.mock.patch('asyncio.base_events.socket') def test_create_datagram_endpoint_no_addrinfo(self, m_socket): m_socket.getaddrinfo.return_value = [] + m_socket.getaddrinfo._is_coroutine = False coro = self.loop.create_datagram_endpoint( MyDatagramProto, local_addr=('localhost', 0)) @@ -681,6 +683,22 @@ unittest.mock.ANY, MyProto, sock, None, None) + def test_call_coroutine(self): + @asyncio.coroutine + def coroutine_function(): + pass + + with self.assertRaises(TypeError): + self.loop.call_soon(coroutine_function) + with self.assertRaises(TypeError): + self.loop.call_soon_threadsafe(coroutine_function) + with self.assertRaises(TypeError): + self.loop.call_later(60, coroutine_function) + with self.assertRaises(TypeError): + self.loop.call_at(self.loop.time() + 60, coroutine_function) + with self.assertRaises(TypeError): + self.loop.run_in_executor(None, coroutine_function) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -402,7 +402,7 @@ NotImplementedError, BaseProactorEventLoop, self.proactor) def test_make_socket_transport(self): - tr = self.loop._make_socket_transport(self.sock, unittest.mock.Mock()) + tr = self.loop._make_socket_transport(self.sock, asyncio.Protocol()) self.assertIsInstance(tr, _ProactorSocketTransport) def test_loop_self_reading(self): diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -44,8 +44,8 @@ def test_make_socket_transport(self): m = unittest.mock.Mock() self.loop.add_reader = unittest.mock.Mock() - self.assertIsInstance( - self.loop._make_socket_transport(m, m), _SelectorSocketTransport) + transport = self.loop._make_socket_transport(m, asyncio.Protocol()) + self.assertIsInstance(transport, _SelectorSocketTransport) @unittest.skipIf(ssl is None, 'No ssl module') def test_make_ssl_transport(self): @@ -54,8 +54,9 @@ self.loop.add_writer = unittest.mock.Mock() self.loop.remove_reader = unittest.mock.Mock() self.loop.remove_writer = unittest.mock.Mock() - self.assertIsInstance( - self.loop._make_ssl_transport(m, m, m, m), _SelectorSslTransport) + waiter = asyncio.Future(loop=self.loop) + transport = self.loop._make_ssl_transport(m, asyncio.Protocol(), m, waiter) + self.assertIsInstance(transport, _SelectorSslTransport) @unittest.mock.patch('asyncio.selector_events.ssl', None) def test_make_ssl_transport_without_ssl_error(self): diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2,8 +2,6 @@ import gc import unittest -import unittest.mock -from unittest.mock import Mock import asyncio from asyncio import test_utils @@ -1358,7 +1356,7 @@ def _check_success(self, **kwargs): a, b, c = [asyncio.Future(loop=self.one_loop) for i in range(3)] fut = asyncio.gather(*self.wrap_futures(a, b, c), **kwargs) - cb = Mock() + cb = test_utils.MockCallback() fut.add_done_callback(cb) b.set_result(1) a.set_result(2) @@ -1380,7 +1378,7 @@ def test_one_exception(self): a, b, c, d, e = [asyncio.Future(loop=self.one_loop) for i in range(5)] fut = asyncio.gather(*self.wrap_futures(a, b, c, d, e)) - cb = Mock() + cb = test_utils.MockCallback() fut.add_done_callback(cb) exc = ZeroDivisionError() a.set_result(1) @@ -1399,7 +1397,7 @@ a, b, c, d = [asyncio.Future(loop=self.one_loop) for i in range(4)] fut = asyncio.gather(*self.wrap_futures(a, b, c, d), return_exceptions=True) - cb = Mock() + cb = test_utils.MockCallback() fut.add_done_callback(cb) exc = ZeroDivisionError() exc2 = RuntimeError() @@ -1460,7 +1458,7 @@ def test_one_cancellation(self): a, b, c, d, e = [asyncio.Future(loop=self.one_loop) for i in range(5)] fut = asyncio.gather(a, b, c, d, e) - cb = Mock() + cb = test_utils.MockCallback() fut.add_done_callback(cb) a.set_result(1) b.cancel() @@ -1479,7 +1477,7 @@ a, b, c, d, e, f = [asyncio.Future(loop=self.one_loop) for i in range(6)] fut = asyncio.gather(a, b, c, d, e, f, return_exceptions=True) - cb = Mock() + cb = test_utils.MockCallback() fut.add_done_callback(cb) a.set_result(1) zde = ZeroDivisionError() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 11:46:07 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 11 Feb 2014 11:46:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2C_Tulip_issue_130?= =?utf-8?q?=3A_Add_more_checks_on_subprocess=5Fexec/subprocess=5Fshell?= Message-ID: <3fNgdC6nl2z7Ljj@mail.python.org> http://hg.python.org/cpython/rev/f729e9ee5dfc changeset: 89146:f729e9ee5dfc user: Victor Stinner date: Tue Feb 11 11:44:56 2014 +0100 summary: asyncio, Tulip issue 130: Add more checks on subprocess_exec/subprocess_shell parameters files: Lib/asyncio/base_events.py | 12 +- Lib/asyncio/subprocess.py | 5 +- Lib/test/test_asyncio/test_base_events.py | 54 ++++++++++- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -558,7 +558,7 @@ stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=False, shell=True, bufsize=0, **kwargs): - if not isinstance(cmd, str): + if not isinstance(cmd, (bytes, str)): raise ValueError("cmd must be a string") if universal_newlines: raise ValueError("universal_newlines must be False") @@ -572,7 +572,7 @@ return transport, protocol @tasks.coroutine - def subprocess_exec(self, protocol_factory, *args, stdin=subprocess.PIPE, + 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): @@ -582,9 +582,15 @@ raise ValueError("shell must be False") if bufsize != 0: raise ValueError("bufsize must be 0") + 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__) protocol = protocol_factory() transport = yield from self._make_subprocess_transport( - protocol, args, False, stdin, stdout, stderr, bufsize, **kwargs) + protocol, popen_args, False, stdin, stdout, stderr, bufsize, **kwargs) return transport, protocol def _add_callback(self, handle): diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -180,7 +180,7 @@ return Process(transport, protocol, loop) @tasks.coroutine -def create_subprocess_exec(*args, stdin=None, stdout=None, stderr=None, +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() @@ -188,7 +188,8 @@ loop=loop) transport, protocol = yield from loop.subprocess_exec( protocol_factory, - *args, stdin=stdin, stdout=stdout, + program, *args, + stdin=stdin, stdout=stdout, stderr=stderr, **kwds) yield from protocol.waiter return Process(transport, protocol, loop) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -3,6 +3,7 @@ import errno import logging import socket +import sys import time import unittest import unittest.mock @@ -234,8 +235,57 @@ self.assertEqual([handle], list(self.loop._ready)) def test_run_until_complete_type_error(self): - self.assertRaises( - TypeError, self.loop.run_until_complete, 'blah') + self.assertRaises(TypeError, + self.loop.run_until_complete, 'blah') + + def test_subprocess_exec_invalid_args(self): + args = [sys.executable, '-c', 'pass'] + + # missing program parameter (empty args) + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_exec, + asyncio.SubprocessProtocol) + + # exepected multiple arguments, not a list + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_exec, + asyncio.SubprocessProtocol, args) + + # program arguments must be strings, not int + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_exec, + asyncio.SubprocessProtocol, sys.executable, 123) + + # universal_newlines, shell, bufsize must not be set + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_exec, + asyncio.SubprocessProtocol, *args, universal_newlines=True) + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_exec, + asyncio.SubprocessProtocol, *args, shell=True) + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_exec, + asyncio.SubprocessProtocol, *args, bufsize=4096) + + def test_subprocess_shell_invalid_args(self): + # exepected a string, not an int or a list + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_shell, + asyncio.SubprocessProtocol, 123) + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_shell, + asyncio.SubprocessProtocol, [sys.executable, '-c', 'pass']) + + # universal_newlines, shell, bufsize must not be set + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_shell, + asyncio.SubprocessProtocol, 'exit 0', universal_newlines=True) + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_shell, + asyncio.SubprocessProtocol, 'exit 0', shell=True) + self.assertRaises(TypeError, + self.loop.run_until_complete, self.loop.subprocess_shell, + asyncio.SubprocessProtocol, 'exit 0', bufsize=4096) class MyProto(asyncio.Protocol): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 11:55:43 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 11 Feb 2014 11:55:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2C_Tulip_issue_131?= =?utf-8?q?=3A_as=5Fcompleted=28=29_and_wait=28=29_now_raises_a_TypeError_?= =?utf-8?q?if?= Message-ID: <3fNgrH19P7z7LjT@mail.python.org> http://hg.python.org/cpython/rev/15a6be05e970 changeset: 89147:15a6be05e970 user: Victor Stinner date: Tue Feb 11 11:54:08 2014 +0100 summary: asyncio, Tulip issue 131: as_completed() and wait() now raises a TypeError if the list of futures is not a list but a Future, Task or coroutine object files: Lib/asyncio/tasks.py | 4 ++ Lib/test/test_asyncio/test_tasks.py | 26 +++++++++++++++++ 2 files changed, 30 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -358,6 +358,8 @@ Note: This does not raise TimeoutError! Futures that aren't done when the timeout occurs are returned in the second set. """ + if isinstance(fs, futures.Future) or iscoroutine(fs): + raise TypeError("expect a list of futures, not %s" % type(fs).__name__) if not fs: raise ValueError('Set of coroutines/Futures is empty.') @@ -474,6 +476,8 @@ Note: The futures 'f' are not necessarily members of fs. """ + if isinstance(fs, futures.Future) or iscoroutine(fs): + raise TypeError("expect a list of futures, not %s" % type(fs).__name__) loop = loop if loop is not None else events.get_event_loop() deadline = None if timeout is None else loop.time() + timeout todo = {async(f, loop=loop) for f in set(fs)} diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -7,6 +7,11 @@ from asyncio import test_utils + at asyncio.coroutine +def coroutine_function(): + pass + + class Dummy: def __repr__(self): @@ -1338,6 +1343,27 @@ child2.set_result(2) test_utils.run_briefly(self.loop) + def test_as_completed_invalid_args(self): + fut = asyncio.Future(loop=self.loop) + + # as_completed() expects a list of futures, not a future instance + self.assertRaises(TypeError, self.loop.run_until_complete, + asyncio.as_completed(fut, loop=self.loop)) + self.assertRaises(TypeError, self.loop.run_until_complete, + asyncio.as_completed(coroutine_function(), loop=self.loop)) + + def test_wait_invalid_args(self): + fut = asyncio.Future(loop=self.loop) + + # wait() expects a list of futures, not a future instance + self.assertRaises(TypeError, self.loop.run_until_complete, + asyncio.wait(fut, loop=self.loop)) + self.assertRaises(TypeError, self.loop.run_until_complete, + asyncio.wait(coroutine_function(), loop=self.loop)) + + # wait() expects at least a future + self.assertRaises(ValueError, self.loop.run_until_complete, + asyncio.wait([], loop=self.loop)) class GatherTestsBase: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 12:33:22 2014 From: python-checkins at python.org (vinay.sajip) Date: Tue, 11 Feb 2014 12:33:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTU4?= =?utf-8?q?=3A_Improved_implementation_of_error_handling=2E?= Message-ID: <3fNhgk6rsBz7LnL@mail.python.org> http://hg.python.org/cpython/rev/41e49f1c5bd8 changeset: 89148:41e49f1c5bd8 branch: 2.7 parent: 89138:51afe7839f8a user: Vinay Sajip date: Tue Feb 11 11:32:40 2014 +0000 summary: Issue #20558: Improved implementation of error handling. files: Lib/logging/config.py | 57 ++++++++++++++++-------------- 1 files changed, 30 insertions(+), 27 deletions(-) diff --git a/Lib/logging/config.py b/Lib/logging/config.py --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -24,8 +24,18 @@ To use, simply 'import logging' and log away! """ -import sys, logging, logging.handlers, socket, struct, os, traceback, re -import types, cStringIO +import cStringIO +import errno +import io +import logging +import logging.handlers +import os +import re +import socket +import struct +import sys +import traceback +import types try: import thread @@ -38,10 +48,7 @@ DEFAULT_LOGGING_CONFIG_PORT = 9030 -if sys.platform == "win32": - RESET_ERROR = 10054 #WSAECONNRESET -else: - RESET_ERROR = 104 #ECONNRESET +RESET_ERROR = errno.ECONNRESET # # The following code implements a socket listener for on-the-fly @@ -510,21 +517,21 @@ level = handler_config.get('level', None) if level: handler.setLevel(logging._checkLevel(level)) - except StandardError, e: + except StandardError as e: raise ValueError('Unable to configure handler ' '%r: %s' % (name, e)) loggers = config.get('loggers', EMPTY_DICT) for name in loggers: try: self.configure_logger(name, loggers[name], True) - except StandardError, e: + except StandardError as e: raise ValueError('Unable to configure logger ' '%r: %s' % (name, e)) root = config.get('root', None) if root: try: self.configure_root(root, True) - except StandardError, e: + except StandardError as e: raise ValueError('Unable to configure root ' 'logger: %s' % e) else: @@ -539,7 +546,7 @@ try: formatters[name] = self.configure_formatter( formatters[name]) - except StandardError, e: + except StandardError as e: raise ValueError('Unable to configure ' 'formatter %r: %s' % (name, e)) # Next, do filters - they don't refer to anything else, either @@ -547,7 +554,7 @@ for name in filters: try: filters[name] = self.configure_filter(filters[name]) - except StandardError, e: + except StandardError as e: raise ValueError('Unable to configure ' 'filter %r: %s' % (name, e)) @@ -561,7 +568,7 @@ handler = self.configure_handler(handlers[name]) handler.name = name handlers[name] = handler - except StandardError, e: + except StandardError as e: if 'target not configured yet' in str(e): deferred.append(name) else: @@ -574,7 +581,7 @@ handler = self.configure_handler(handlers[name]) handler.name = name handlers[name] = handler - except StandardError, e: + except StandardError as e: raise ValueError('Unable to configure handler ' '%r: %s' % (name, e)) @@ -615,7 +622,7 @@ existing.remove(name) try: self.configure_logger(name, loggers[name]) - except StandardError, e: + except StandardError as e: raise ValueError('Unable to configure logger ' '%r: %s' % (name, e)) @@ -638,7 +645,7 @@ if root: try: self.configure_root(root) - except StandardError, e: + except StandardError as e: raise ValueError('Unable to configure root ' 'logger: %s' % e) finally: @@ -650,7 +657,7 @@ factory = config['()'] # for use in exception handler try: result = self.configure_custom(config) - except TypeError, te: + except TypeError as te: if "'format'" not in str(te): raise #Name of parameter changed from fmt to format. @@ -680,7 +687,7 @@ for f in filters: try: filterer.addFilter(self.config['filters'][f]) - except StandardError, e: + except StandardError as e: raise ValueError('Unable to add filter %r: %s' % (f, e)) def configure_handler(self, config): @@ -689,7 +696,7 @@ if formatter: try: formatter = self.config['formatters'][formatter] - except StandardError, e: + except StandardError as e: raise ValueError('Unable to set formatter ' '%r: %s' % (formatter, e)) level = config.pop('level', None) @@ -711,7 +718,7 @@ config['class'] = cname # restore for deferred configuration raise StandardError('target not configured yet') config['target'] = th - except StandardError, e: + except StandardError as e: raise ValueError('Unable to set target handler ' '%r: %s' % (config['target'], e)) elif issubclass(klass, logging.handlers.SMTPHandler) and\ @@ -724,7 +731,7 @@ kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) try: result = factory(**kwargs) - except TypeError, te: + except TypeError as te: if "'stream'" not in str(te): raise #The argument name changed from strm to stream @@ -746,7 +753,7 @@ for h in handlers: try: logger.addHandler(self.config['handlers'][h]) - except StandardError, e: + except StandardError as e: raise ValueError('Unable to add handler %r: %s' % (h, e)) def common_logger_config(self, logger, config, incremental=False): @@ -841,13 +848,9 @@ traceback.print_exc() if self.server.ready: self.server.ready.set() - except socket.error, e: - if not isinstance(e.args, tuple): + except socket.error as e: + if e.errno != RESET_ERROR: raise - else: - errcode = e.args[0] - if errcode != RESET_ERROR: - raise class ConfigSocketReceiver(ThreadingTCPServer): """ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 14:13:52 2014 From: python-checkins at python.org (r.david.murray) Date: Tue, 11 Feb 2014 14:13:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_=5F=5Fcomplex?= =?utf-8?q?=5F=5F_may_not_return_float=2C_=2Eso_may_have_multiple_python_m?= =?utf-8?q?odules?= Message-ID: <3fNkvh56YWz7Lqs@mail.python.org> http://hg.python.org/cpython/rev/7cfbebadb90b changeset: 89149:7cfbebadb90b parent: 89147:15a6be05e970 user: R David Murray date: Tue Feb 11 08:13:10 2014 -0500 summary: whatsnew: __complex__ may not return float, .so may have multiple python modules Also a NEWS wording fixup. files: Doc/whatsnew/3.4.rst | 9 +++++++++ Misc/NEWS | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1443,6 +1443,10 @@ values for its constants from the C header files, instead of having the values hard-coded in the python module as was previously the case. +* Loading multiple python modules from a single OS module (``.so``, ``.dll``) + now works correctly (previously it silently returned the first python + module in the file). (Contributed by V?clav ?milauer in :issue:`16421`.) + Significant Optimizations @@ -1725,6 +1729,11 @@ :exc:`ValueError` if given a negative length; previously it returned nonsense values (:issue:`14794`). +* The :class:`complex` constructor, unlike the :mod:`cmath` functions, was + incorrectly accepting :class:`float` values if an object's ``__complex__`` + special method returned one. This now raises a :exc:`TypeError`. + (:issue:`16290`.) + Changes in the C API -------------------- diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2262,10 +2262,10 @@ builtins. - Issue #16455: On FreeBSD and Solaris, if the locale is C, the - ASCII/surrogateescape codec is now used, instead of the locale encoding, to + ASCII/surrogateescape codec is now used (instead of the locale encoding) to decode the command line arguments. This change fixes inconsistencies with - os.fsencode() and os.fsdecode() because these operating systems announces an - ASCII locale encoding, whereas the ISO-8859-1 encoding is used in practice. + os.fsencode() and os.fsdecode(), because these operating systems announce an + ASCII locale encoding, but actually use the ISO-8859-1 encoding in practice. - Issue #16562: Optimize dict equality testing. Patch by Serhiy Storchaka. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 16:09:57 2014 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 11 Feb 2014 16:09:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_dynamic_initializer?= =?utf-8?q?_lists_for_c89_compliance_=28closes_=2320595=29?= Message-ID: <3fNnTd6PnBz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/417a468ae755 changeset: 89150:417a468ae755 user: Benjamin Peterson date: Tue Feb 11 10:09:27 2014 -0500 summary: remove dynamic initializer lists for c89 compliance (closes #20595) files: Misc/NEWS | 2 ++ Python/getargs.c | 14 +++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #20595: Make getargs.c C89 compliant. + Library ------- diff --git a/Python/getargs.c b/Python/getargs.c --- a/Python/getargs.c +++ b/Python/getargs.c @@ -200,8 +200,6 @@ { char msgbuf[256]; int levels[32]; - freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; - freelist_t freelist = {static_entries, 0, 0}; const char *fname = NULL; const char *message = NULL; int min = -1; @@ -212,6 +210,12 @@ Py_ssize_t i, len; char *msg; int compat = flags & FLAG_COMPAT; + freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; + freelist_t freelist; + + freelist.entries = static_entries; + freelist.first_available = 0; + freelist.entries_malloced = 0; assert(compat || (args != (PyObject*)NULL)); flags = flags & ~FLAG_COMPAT; @@ -1439,7 +1443,11 @@ Py_ssize_t nargs, nkeywords; PyObject *current_arg; freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; - freelist_t freelist = {static_entries, 0, 0}; + freelist_t freelist; + + freelist.entries = static_entries; + freelist.first_available = 0; + freelist.entries_malloced = 0; assert(args != NULL && PyTuple_Check(args)); assert(keywords == NULL || PyDict_Check(keywords)); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 16:19:23 2014 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 11 Feb 2014 16:19:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_avoid_name_cla?= =?utf-8?q?sh_with_posix=5Fclose_=28closes_=2320594=29?= Message-ID: <3fNnhW2MYszS0d@mail.python.org> http://hg.python.org/cpython/rev/1d253360d5a6 changeset: 89151:1d253360d5a6 branch: 2.7 parent: 89148:41e49f1c5bd8 user: Benjamin Peterson date: Tue Feb 11 10:16:16 2014 -0500 summary: avoid name clash with posix_close (closes #20594) files: Misc/NEWS | 2 ++ Modules/posixmodule.c | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -44,6 +44,8 @@ Library ------- +- Issue #20594: Avoid name clash with the libc function posix_close. + - Issue #19856: shutil.move() failed to move a directory to other directory on Windows if source name ends with os.altsep. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6581,8 +6581,12 @@ "close(fd)\n\n\ Close a file descriptor (for low level IO)."); -static PyObject * -posix_close(PyObject *self, PyObject *args) +/* +The underscore at end of function name avoids a name clash with the libc +function posix_close. +*/ +static PyObject * +posix_close_(PyObject *self, PyObject *args) { int fd, res; if (!PyArg_ParseTuple(args, "i:close", &fd)) @@ -8960,7 +8964,7 @@ {"tcsetpgrp", posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__}, #endif /* HAVE_TCSETPGRP */ {"open", posix_open, METH_VARARGS, posix_open__doc__}, - {"close", posix_close, METH_VARARGS, posix_close__doc__}, + {"close", posix_close_, METH_VARARGS, posix_close__doc__}, {"closerange", posix_closerange, METH_VARARGS, posix_closerange__doc__}, {"dup", posix_dup, METH_VARARGS, posix_dup__doc__}, {"dup2", posix_dup2, METH_VARARGS, posix_dup2__doc__}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 16:19:24 2014 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 11 Feb 2014 16:19:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_avoid_name_cla?= =?utf-8?q?sh_with_posix=5Fclose_=28closes_=2320594=29?= Message-ID: <3fNnhX5LxTz7Ljt@mail.python.org> http://hg.python.org/cpython/rev/021dd3c65198 changeset: 89152:021dd3c65198 branch: 3.3 parent: 89139:373ec8711ad0 user: Benjamin Peterson date: Tue Feb 11 10:16:16 2014 -0500 summary: avoid name clash with posix_close (closes #20594) files: Misc/NEWS | 2 ++ Modules/posixmodule.c | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -20,6 +20,8 @@ Library ------- +- Issue #20594: Avoid name clash with the libc function posix_close. + - Issue #19856: shutil.move() failed to move a directory to other directory on Windows if source name ends with os.altsep. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7844,8 +7844,12 @@ "close(fd)\n\n\ Close a file descriptor (for low level IO)."); -static PyObject * -posix_close(PyObject *self, PyObject *args) +/* +The underscore at end of function name avoids a name clash with the libc +function posix_close. +*/ +static PyObject * +posix_close_(PyObject *self, PyObject *args) { int fd, res; if (!PyArg_ParseTuple(args, "i:close", &fd)) @@ -11261,7 +11265,7 @@ {"open", (PyCFunction)posix_open,\ METH_VARARGS | METH_KEYWORDS, posix_open__doc__}, - {"close", posix_close, METH_VARARGS, posix_close__doc__}, + {"close", posix_close_, METH_VARARGS, posix_close__doc__}, {"closerange", posix_closerange, METH_VARARGS, posix_closerange__doc__}, {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__}, {"dup", posix_dup, METH_VARARGS, posix_dup__doc__}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 16:19:26 2014 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 11 Feb 2014 16:19:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4zICgjMjA1OTQp?= Message-ID: <3fNnhZ1583z7Ljj@mail.python.org> http://hg.python.org/cpython/rev/400a8e4599d9 changeset: 89153:400a8e4599d9 parent: 89150:417a468ae755 parent: 89152:021dd3c65198 user: Benjamin Peterson date: Tue Feb 11 10:19:12 2014 -0500 summary: merge 3.3 (#20594) files: Misc/NEWS | 2 ++ Modules/posixmodule.c | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,8 @@ Library ------- +- Issue #20594: Avoid name clash with the libc function posix_close. + - Issue #19856: shutil.move() failed to move a directory to other directory on Windows if source name ends with os.altsep. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7763,8 +7763,12 @@ "close(fd)\n\n\ Close a file descriptor (for low level IO)."); -static PyObject * -posix_close(PyObject *self, PyObject *args) +/* +The underscore at end of function name avoids a name clash with the libc +function posix_close. +*/ +static PyObject * +posix_close_(PyObject *self, PyObject *args) { int fd, res; if (!PyArg_ParseTuple(args, "i:close", &fd)) @@ -11422,7 +11426,7 @@ {"open", (PyCFunction)posix_open,\ METH_VARARGS | METH_KEYWORDS, posix_open__doc__}, - {"close", posix_close, METH_VARARGS, posix_close__doc__}, + {"close", posix_close_, METH_VARARGS, posix_close__doc__}, {"closerange", posix_closerange, METH_VARARGS, posix_closerange__doc__}, {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__}, {"dup", posix_dup, METH_VARARGS, posix_dup__doc__}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 17:54:19 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 11 Feb 2014 17:54:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320505=3A_Remove_d?= =?utf-8?q?ebug_code?= Message-ID: <3fNqp36zr0z7LjN@mail.python.org> http://hg.python.org/cpython/rev/360976a6d8b9 changeset: 89154:360976a6d8b9 user: Victor Stinner date: Tue Feb 11 17:53:47 2014 +0100 summary: Issue #20505: Remove debug code files: Lib/asyncio/base_events.py | 20 -------------------- 1 files changed, 0 insertions(+), 20 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -646,27 +646,7 @@ else: logger.log(level, 'poll took %.3f seconds', t1-t0) else: - t0_monotonic = time.monotonic() - t0 = time.perf_counter() event_list = self._selector.select(timeout) - dt = time.perf_counter() - t0 - dt_monotonic = time.monotonic() - t0_monotonic - if (not event_list and timeout - and (dt < timeout or dt_monotonic < timeout)): - selector = self._selector.__class__.__name__ - if (selector.startswith(("Poll", "Epoll", "Iocp")) - or timeout > 1e-3 or dt > 1e-3): - unit, factor = "ms", 1e3 - else: - unit, factor = "us", 1e6 - print("asyncio: %s.select(%.4f %s) took %.3f %s" - " (monotonic=%.3f %s, clock res=%.3f %s)" - % (self._selector.__class__.__name__, - timeout * factor, unit, - dt * factor, unit, - dt_monotonic * factor, unit, - self._clock_resolution * factor, unit), - file=sys.__stderr__, flush=True) self._process_events(event_list) # Handle 'later' callbacks that are ready. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 18:21:13 2014 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 11 Feb 2014 18:21:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Deprecate_Popen=2Ewait=28?= =?utf-8?q?=29=27s_undocumented_endtime_parameter=2E_issue20572=2E?= Message-ID: <3fNrP51Dm4z7LjV@mail.python.org> http://hg.python.org/cpython/rev/73793590d97b changeset: 89155:73793590d97b user: Gregory P. Smith date: Tue Feb 11 09:21:03 2014 -0800 summary: Deprecate Popen.wait()'s undocumented endtime parameter. issue20572. files: Doc/library/subprocess.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -639,6 +639,11 @@ .. versionchanged:: 3.3 *timeout* was added. + .. deprecated:: 3.4 + + Do not use the undocumented *endtime* parameter. It is was + unintentionally exposed in 3.3 but was intended to be private + for internal use. Use *timeout* instead. .. method:: Popen.communicate(input=None, timeout=None) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 18:40:32 2014 From: python-checkins at python.org (r.david.murray) Date: Tue, 11 Feb 2014 18:40:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_undocumented_P?= =?utf-8?q?open=2Ewait_endtime_is_deprecated=2E?= Message-ID: <3fNrqN1l2Vz7LjY@mail.python.org> http://hg.python.org/cpython/rev/48bf5edab3bc changeset: 89156:48bf5edab3bc user: R David Murray date: Tue Feb 11 12:40:18 2014 -0500 summary: whatsnew: undocumented Popen.wait endtime is deprecated. files: Doc/whatsnew/3.4.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1529,6 +1529,10 @@ as deprecated in its docstring for quite some time. It now emits a :exc:`DeprecationWarning` and will be removed completely in Python 3.5. +* The undocumented *endtime* argument to :meth:`subprocess.Popen.wait` should + not have been exposed and is hopefully not in use; it is deprecated and + will mostly likely be removed in Python 3.5. + Deprecated Functions and Types in the C API ------------------------------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 11 18:41:34 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 11 Feb 2014 18:41:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320495=3A_Skip_tes?= =?utf-8?q?t=5Fread=5Fpty=5Foutput=28=29_of_test=5Fasyncio_on_FreeBSD_olde?= =?utf-8?q?r_than?= Message-ID: <3fNrrZ6pNdz7LjY@mail.python.org> http://hg.python.org/cpython/rev/2ba583191550 changeset: 89157:2ba583191550 user: Victor Stinner date: Tue Feb 11 18:40:56 2014 +0100 summary: Issue #20495: Skip test_read_pty_output() of test_asyncio on FreeBSD older than FreeBSD 8 files: Lib/test/test_asyncio/test_events.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -956,6 +956,8 @@ # 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) + # 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): proto = None -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 00:34:45 2014 From: python-checkins at python.org (r.david.murray) Date: Wed, 12 Feb 2014 00:34:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_object=2E=5F?= =?utf-8?q?=5Fformat=5F=5F_raises_TypeError_on_non-empty_string=2E?= Message-ID: <3fP0h53Jtmz7Ljk@mail.python.org> http://hg.python.org/cpython/rev/f56b98143792 changeset: 89158:f56b98143792 user: R David Murray date: Tue Feb 11 18:34:22 2014 -0500 summary: whatsnew: object.__format__ raises TypeError on non-empty string. See issues #7994 and #9856. I also modified with wording of the format doc entry to better match what really happens, and added a versionchanged to the datamodel object.__format__ section. files: Doc/library/functions.rst | 9 +++++---- Doc/reference/datamodel.rst | 4 ++++ Doc/whatsnew/3.4.rst | 9 +++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -540,12 +540,13 @@ A call to ``format(value, format_spec)`` is translated to ``type(value).__format__(format_spec)`` which bypasses the instance dictionary when searching for the value's :meth:`__format__` method. A - :exc:`TypeError` exception is raised if the method is not found or if either - the *format_spec* or the return value are not strings. + :exc:`TypeError` exception is raised if the method search reaches + :mod:`object` and the *format_spec* is non-empty, or if either the + *format_spec* or the return value are not strings. - .. versionadded:: 3.4 + .. versionchanged:: 3.4 ``object().__format__(format_spec)`` raises :exc:`TypeError` - if *format_spec* is not empty string. + if *format_spec* is not an empty string. .. _func-frozenset: diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1226,6 +1226,10 @@ The return value must be a string object. + .. versionchanged:: 3.4 + The __format__ method of ``object`` itself raises a :exc:`TypeError` + if passed any non-empty string. + .. _richcmpfuncs: .. method:: object.__lt__(self, other) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1600,6 +1600,15 @@ * :class:`inspect.Signature`: positional-only parameters are now required to have a valid name. +* :meth:`object.__format__` no longer accepts non-empty format strings, it now + raises a :exc:`TypeError` instead. Using a non-empty string has been + deprecated since Python 3.2. This change has been made to prevent a + situation where previously working (but incorrect) code would start failing + if an object gained a __format__ method, which means that your code may now + raise a :exc:`TypeError` if you are using an ``'s'`` format code with objects + that do not have a __format__ method that handles it. See :issue:`7994` for + background. + Code Cleanups ------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 02:36:50 2014 From: python-checkins at python.org (ned.deily) Date: Wed, 12 Feb 2014 02:36:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Add_information_about_ins?= =?utf-8?q?talling_Xcode_on_OS_X_to_the_Getting_Started_section=2E?= Message-ID: <3fP3Ny1v1Tz7Ll0@mail.python.org> http://hg.python.org/devguide/rev/2368fbd290e8 changeset: 666:2368fbd290e8 user: Ned Deily date: Tue Feb 11 17:36:39 2014 -0800 summary: Add information about installing Xcode on OS X to the Getting Started section. files: setup.rst | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/setup.rst b/setup.rst --- a/setup.rst +++ b/setup.rst @@ -105,6 +105,27 @@ $ sudo apt-get build-dep python3 +For Mac OS X systems, it is generally easiest to use the C compiler and other +development utilities provided by Apple's Xcode Developer Tools. There are +specific versions supported by Apple for each major release of OS X. For +current releases, Xcode is available as a no-cost download from Apple's App +Store. Xcode versions for older releases are available through +`the Apple Developer web site `_. +Note that while the Xcode IDE application itself is not needed to build Python, +the development components packaged inside it may be. You should also install +the Xcode Command Line Tools component to ensure build tools and system header +files are installed in their conventional locations (``/usr/bin`` and +``/usr/include``). How the command line tools are installed varies by OS X +and Xcode release. In earlier releases, there may be a separate installer +download. For OS X 10.7 and 10.8, there is an option in the Xcode app +Preferences menu. For OS X 10.9 (Mavericks), run the following:: + + $ xcode-select --install + +Also note that OS X does not include several libraries used by the Python +standard library, including ``libzma``, so expect to see some extension module +build failures unless you install local copies of them. + There will sometimes be optional modules added for a new release which won't yet be identified in the OS level build dependencies. In those cases, just ask for assistance on the core-mentorship list. If working on bug -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Wed Feb 12 03:00:32 2014 From: python-checkins at python.org (ned.deily) Date: Wed, 12 Feb 2014 03:00:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Add_references?= =?utf-8?q?_for_Xcode_and_the_Python_Developer=27s_Guide?= Message-ID: <3fP3wJ40YTz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/08f5b3c1674a changeset: 89159:08f5b3c1674a branch: 2.7 parent: 89151:1d253360d5a6 user: Ned Deily date: Tue Feb 11 17:57:14 2014 -0800 summary: Add references for Xcode and the Python Developer's Guide to the internal Mac/README file. files: Mac/README | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Mac/README b/Mac/README --- a/Mac/README +++ b/Mac/README @@ -81,6 +81,13 @@ $ ./configure --enable-universalsdk=/ +In general, universal builds depend on specific features provided by the +Apple-supplied compilers and other build tools included in Apple's Xcode +development tools. You should install Xcode and the command line tools +component appropriate for the OS X release you are running on. See the +Python Developer's Guide (http://docs.python.org/devguide/setup.html) +for more information. + 2.1 Flavours of universal binaries .................................. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 03:00:33 2014 From: python-checkins at python.org (ned.deily) Date: Wed, 12 Feb 2014 03:00:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Add_references?= =?utf-8?q?_for_Xcode_and_the_Python_Developer=27s_Guide?= Message-ID: <3fP3wK5V5Xz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/188c046d7afb changeset: 89160:188c046d7afb branch: 3.3 parent: 89152:021dd3c65198 user: Ned Deily date: Tue Feb 11 17:57:37 2014 -0800 summary: Add references for Xcode and the Python Developer's Guide to the internal Mac/README file. files: Mac/README | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Mac/README b/Mac/README --- a/Mac/README +++ b/Mac/README @@ -86,6 +86,13 @@ and the 10.4u SDK. Starting with Xcode 3 and OS X 10.5, more configurations are available. +In general, universal builds depend on specific features provided by the +Apple-supplied compilers and other build tools included in Apple's Xcode +development tools. You should install Xcode and the command line tools +component appropriate for the OS X release you are running on. See the +Python Developer's Guide (http://docs.python.org/devguide/setup.html) +for more information. + 2.1 Flavors of universal binaries ................................. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 03:00:34 2014 From: python-checkins at python.org (ned.deily) Date: Wed, 12 Feb 2014 03:00:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Add_references_for_Xcode_and_the_Python_Developer=27s_Gu?= =?utf-8?q?ideto_the_internal?= Message-ID: <3fP3wL6vB0z7LjX@mail.python.org> http://hg.python.org/cpython/rev/b3d639d50bb8 changeset: 89161:b3d639d50bb8 parent: 89158:f56b98143792 parent: 89160:188c046d7afb user: Ned Deily date: Tue Feb 11 17:59:47 2014 -0800 summary: Add references for Xcode and the Python Developer's Guideto the internal Mac/README file. files: Mac/README | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Mac/README b/Mac/README --- a/Mac/README +++ b/Mac/README @@ -86,6 +86,13 @@ and the 10.4u SDK. Starting with Xcode 3 and OS X 10.5, more configurations are available. +In general, universal builds depend on specific features provided by the +Apple-supplied compilers and other build tools included in Apple's Xcode +development tools. You should install Xcode and the command line tools +component appropriate for the OS X release you are running on. See the +Python Developer's Guide (http://docs.python.org/devguide/setup.html) +for more information. + 2.1 Flavors of universal binaries ................................. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 05:35:15 2014 From: python-checkins at python.org (r.david.murray) Date: Wed, 12 Feb 2014 05:35:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_command=2Ecom_?= =?utf-8?q?support_gone=2C_int_*base*_can_be_=5F=5Findex=5F=5F_but_not_flo?= =?utf-8?b?YXQu?= Message-ID: <3fP7Lq0k97z7LkH@mail.python.org> http://hg.python.org/cpython/rev/f6ac400d301e changeset: 89162:f6ac400d301e user: R David Murray date: Tue Feb 11 23:34:14 2014 -0500 summary: whatsnew: command.com support gone, int *base* can be __index__ but not float. files: Doc/whatsnew/3.4.rst | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -368,6 +368,10 @@ buffer objects as arguments. (Contributed by Antoine Pitrou in :issue:`15958`.) +* The :class:`int` constructor now accepts any object that has an ``__index__`` + method for its *base* argument. (Contributed by Mark Dickinson in + :issue:`16772`.) + New Modules =========== @@ -1563,6 +1567,7 @@ * OS/2 (:issue:`16135`). * Windows 2000 (changeset e52df05b496a). +* Windows systems where ``COMSPEC`` points to ``command.com`` (:issue:`14470`). * VMS (:issue:`16136`). @@ -1747,6 +1752,10 @@ special method returned one. This now raises a :exc:`TypeError`. (:issue:`16290`.) +* The :class:`int` constructor in 3.2 and 3.3 erroneously accept :class:`float` + values for the *base* parameter. It is unlikely anyone was doing this, but + if so, it will now raise a :exc:`TypeError` (:issue:`16772`). + Changes in the C API -------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 06:02:56 2014 From: python-checkins at python.org (r.david.murray) Date: Wed, 12 Feb 2014 06:02:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_os=2Epath=2Esa?= =?utf-8?q?mestat_on_windows=2C_keyword_defaults_evaluation_order=2E?= Message-ID: <3fP7ym0mcJz7LjN@mail.python.org> http://hg.python.org/cpython/rev/353100045194 changeset: 89163:353100045194 user: R David Murray date: Wed Feb 12 00:02:34 2014 -0500 summary: whatsnew: os.path.samestat on windows, keyword defaults evaluation order. files: Doc/library/os.path.rst | 2 +- Doc/whatsnew/3.4.rst | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -251,7 +251,7 @@ .. function:: samefile(path1, path2) Return ``True`` if both pathname arguments refer to the same file or directory. - On Unix, this is determined by the device number and i-node number and raises an + This is determined by the device number and i-node number and raises an exception if a :func:`os.stat` call on either pathname fails. Availability: Unix, Windows. diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -955,6 +955,10 @@ terms of the new :mod:`os` function). (Contributed by Trent Nelson, Yogesh Chaudhari, Victor Stinner, and Charles-Fran?ois Natali in :issue:`17914`.) +:func:`os.path.samestat` is now available on the Windows platform (and the +:func:`os.path.samefile` implementation is now shared between Unix and +Windows). (Contributed by Brian Curtin in :issue:`11939`.) + pdb --- @@ -1752,9 +1756,13 @@ special method returned one. This now raises a :exc:`TypeError`. (:issue:`16290`.) -* The :class:`int` constructor in 3.2 and 3.3 erroneously accept :class:`float` +* The :class:`int` constructor in 3.2 and 3.3 erroneously accepts :class:`float` values for the *base* parameter. It is unlikely anyone was doing this, but - if so, it will now raise a :exc:`TypeError` (:issue:`16772`). + if so, it will now raise a :exc:`TypeError` (:issue:`16772`). + +* Defaults for keyword-only arguments are now evaluated *after* defaults for + regular keyword arguments, instead of before. Hopefully no one wrote any + code that depends on the previous buggy behavior (:issue:`16967`). Changes in the C API -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Wed Feb 12 08:00:59 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 12 Feb 2014 08:00:59 +0100 Subject: [Python-checkins] Daily reference leaks (b3d639d50bb8): sum=10 Message-ID: results for b3d639d50bb8 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 4] memory blocks, sum=4 test_site leaked [2, -2, 2] references, sum=2 test_site leaked [2, -2, 2] memory blocks, sum=2 test_xmlrpc_net leaked [0, 2, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog5Ea8EV', '-x'] From python-checkins at python.org Wed Feb 12 08:56:12 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 12 Feb 2014 08:56:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE5MjU1?= =?utf-8?q?=3A_Clear_error_after_failed_PyDict=5FSetItem=28=29_on_shutdown?= =?utf-8?q?=2E?= Message-ID: <3fPCph1btGz7LjR@mail.python.org> http://hg.python.org/cpython/rev/c6e7ba7eee88 changeset: 89164:c6e7ba7eee88 branch: 2.7 parent: 89159:08f5b3c1674a user: Serhiy Storchaka date: Wed Feb 12 09:54:48 2014 +0200 summary: Issue #19255: Clear error after failed PyDict_SetItem() on shutdown. This silences a Coverity complain. files: Objects/moduleobject.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -122,7 +122,8 @@ if (s[0] == '_' && s[1] != '_') { if (Py_VerboseFlag > 1) PySys_WriteStderr("# clear[1] %s\n", s); - PyDict_SetItem(d, key, Py_None); + if (PyDict_SetItem(d, key, Py_None) != 0) + PyErr_Clear(); } } } @@ -135,7 +136,8 @@ if (s[0] != '_' || strcmp(s, "__builtins__") != 0) { if (Py_VerboseFlag > 1) PySys_WriteStderr("# clear[2] %s\n", s); - PyDict_SetItem(d, key, Py_None); + if (PyDict_SetItem(d, key, Py_None) != 0) + PyErr_Clear(); } } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 08:56:13 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 12 Feb 2014 08:56:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE5MjU1?= =?utf-8?q?=3A_Clear_error_after_failed_PyDict=5FSetItem=28=29_on_shutdown?= =?utf-8?q?=2E?= Message-ID: <3fPCpj3GbKz7Lk7@mail.python.org> http://hg.python.org/cpython/rev/ffc4f03adcac changeset: 89165:ffc4f03adcac branch: 3.3 parent: 89160:188c046d7afb user: Serhiy Storchaka date: Wed Feb 12 09:55:01 2014 +0200 summary: Issue #19255: Clear error after failed PyDict_SetItem() on shutdown. This silences a Coverity complain. files: Objects/moduleobject.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -300,7 +300,8 @@ else PyErr_Clear(); } - PyDict_SetItem(d, key, Py_None); + if (PyDict_SetItem(d, key, Py_None) != 0) + PyErr_Clear(); } } } @@ -319,7 +320,8 @@ else PyErr_Clear(); } - PyDict_SetItem(d, key, Py_None); + if (PyDict_SetItem(d, key, Py_None) != 0) + PyErr_Clear(); } } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 08:56:14 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 12 Feb 2014 08:56:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2319255=3A_Clear_error_after_failed_PyDict=5FSetI?= =?utf-8?q?tem=28=29_on_shutdown=2E?= Message-ID: <3fPCpk52j8z7Lkg@mail.python.org> http://hg.python.org/cpython/rev/efaf12106d68 changeset: 89166:efaf12106d68 parent: 89163:353100045194 parent: 89165:ffc4f03adcac user: Serhiy Storchaka date: Wed Feb 12 09:55:45 2014 +0200 summary: Issue #19255: Clear error after failed PyDict_SetItem() on shutdown. This silences a Coverity complain. files: Objects/moduleobject.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -330,7 +330,8 @@ else PyErr_Clear(); } - PyDict_SetItem(d, key, Py_None); + if (PyDict_SetItem(d, key, Py_None) != 0) + PyErr_Clear(); } } } @@ -349,7 +350,8 @@ else PyErr_Clear(); } - PyDict_SetItem(d, key, Py_None); + if (PyDict_SetItem(d, key, Py_None) != 0) + PyErr_Clear(); } } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 09:55:37 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 12 Feb 2014 09:55:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE3Njcx?= =?utf-8?q?=3A_Fixed_a_crash_when_use_non-initialized_io=2EBufferedRWPair?= =?utf-8?q?=2E?= Message-ID: <3fPF7F3Tm8z7Lkw@mail.python.org> http://hg.python.org/cpython/rev/712b4665955d changeset: 89167:712b4665955d branch: 2.7 parent: 89164:c6e7ba7eee88 user: Serhiy Storchaka date: Wed Feb 12 10:52:07 2014 +0200 summary: Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. Based on patch by Stephen Tu. files: Lib/test/test_io.py | 38 ++++++++++++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_io/bufferedio.c | 9 +++++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -793,6 +793,16 @@ bufio.__init__(rawio) self.assertEqual(b"abc", bufio.read()) + def test_uninitialized(self): + bufio = self.tp.__new__(self.tp) + del bufio + bufio = self.tp.__new__(self.tp) + self.assertRaisesRegexp((ValueError, AttributeError), + 'uninitialized|has no attribute', + bufio.read, 0) + bufio.__init__(self.MockRawIO()) + self.assertEqual(bufio.read(0), b'') + def test_read(self): for arg in (None, 7): rawio = self.MockRawIO((b"abc", b"d", b"efg")) @@ -1029,6 +1039,16 @@ bufio.flush() self.assertEqual(b"".join(rawio._write_stack), b"abcghi") + def test_uninitialized(self): + bufio = self.tp.__new__(self.tp) + del bufio + bufio = self.tp.__new__(self.tp) + self.assertRaisesRegexp((ValueError, AttributeError), + 'uninitialized|has no attribute', + bufio.write, b'') + bufio.__init__(self.MockRawIO()) + self.assertEqual(bufio.write(b''), 0) + def test_detach_flush(self): raw = self.MockRawIO() buf = self.tp(raw) @@ -1313,6 +1333,20 @@ pair = self.tp(self.MockRawIO(), self.MockRawIO()) self.assertFalse(pair.closed) + def test_uninitialized(self): + pair = self.tp.__new__(self.tp) + del pair + pair = self.tp.__new__(self.tp) + self.assertRaisesRegexp((ValueError, AttributeError), + 'uninitialized|has no attribute', + pair.read, 0) + self.assertRaisesRegexp((ValueError, AttributeError), + 'uninitialized|has no attribute', + pair.write, b'') + pair.__init__(self.MockRawIO(), self.MockRawIO()) + self.assertEqual(pair.read(0), b'') + self.assertEqual(pair.write(b''), 0) + def test_detach(self): pair = self.tp(self.MockRawIO(), self.MockRawIO()) self.assertRaises(self.UnsupportedOperation, pair.detach) @@ -1440,6 +1474,10 @@ BufferedReaderTest.test_constructor(self) BufferedWriterTest.test_constructor(self) + def test_uninitialized(self): + BufferedReaderTest.test_uninitialized(self) + BufferedWriterTest.test_uninitialized(self) + def test_read_and_write(self): raw = self.MockRawIO((b"asdf", b"ghjk")) rw = self.tp(raw, 8) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -44,6 +44,9 @@ Library ------- +- Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. + Based on patch by Stephen Tu. + - Issue #20594: Avoid name clash with the libc function posix_close. - Issue #19856: shutil.move() failed to move a directory to other directory diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -2129,9 +2129,14 @@ static PyObject * _forward_call(buffered *self, const char *name, PyObject *args) { - PyObject *func = PyObject_GetAttrString((PyObject *)self, name); - PyObject *ret; + PyObject *func, *ret; + if (self == NULL) { + PyErr_SetString(PyExc_ValueError, + "I/O operation on uninitialized object"); + return NULL; + } + func = PyObject_GetAttrString((PyObject *)self, name); if (func == NULL) { PyErr_SetString(PyExc_AttributeError, name); return NULL; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 09:55:40 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 12 Feb 2014 09:55:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE3Njcx?= =?utf-8?q?=3A_Fixed_a_crash_when_use_non-initialized_io=2EBufferedRWPair?= =?utf-8?q?=2E?= Message-ID: <3fPF7J5fDyz7LlD@mail.python.org> http://hg.python.org/cpython/rev/25ff4625680d changeset: 89168:25ff4625680d branch: 3.3 parent: 89165:ffc4f03adcac user: Serhiy Storchaka date: Wed Feb 12 10:52:35 2014 +0200 summary: Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. Based on patch by Stephen Tu. files: Lib/test/test_io.py | 38 ++++++++++++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_io/bufferedio.c | 9 +++++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -846,6 +846,16 @@ bufio.__init__(rawio) self.assertEqual(b"abc", bufio.read()) + def test_uninitialized(self): + bufio = self.tp.__new__(self.tp) + del bufio + bufio = self.tp.__new__(self.tp) + self.assertRaisesRegex((ValueError, AttributeError), + 'uninitialized|has no attribute', + bufio.read, 0) + bufio.__init__(self.MockRawIO()) + self.assertEqual(bufio.read(0), b'') + def test_read(self): for arg in (None, 7): rawio = self.MockRawIO((b"abc", b"d", b"efg")) @@ -1096,6 +1106,16 @@ bufio.flush() self.assertEqual(b"".join(rawio._write_stack), b"abcghi") + def test_uninitialized(self): + bufio = self.tp.__new__(self.tp) + del bufio + bufio = self.tp.__new__(self.tp) + self.assertRaisesRegex((ValueError, AttributeError), + 'uninitialized|has no attribute', + bufio.write, b'') + bufio.__init__(self.MockRawIO()) + self.assertEqual(bufio.write(b''), 0) + def test_detach_flush(self): raw = self.MockRawIO() buf = self.tp(raw) @@ -1379,6 +1399,20 @@ pair = self.tp(self.MockRawIO(), self.MockRawIO()) self.assertFalse(pair.closed) + def test_uninitialized(self): + pair = self.tp.__new__(self.tp) + del pair + pair = self.tp.__new__(self.tp) + self.assertRaisesRegex((ValueError, AttributeError), + 'uninitialized|has no attribute', + pair.read, 0) + self.assertRaisesRegex((ValueError, AttributeError), + 'uninitialized|has no attribute', + pair.write, b'') + pair.__init__(self.MockRawIO(), self.MockRawIO()) + self.assertEqual(pair.read(0), b'') + self.assertEqual(pair.write(b''), 0) + def test_detach(self): pair = self.tp(self.MockRawIO(), self.MockRawIO()) self.assertRaises(self.UnsupportedOperation, pair.detach) @@ -1505,6 +1539,10 @@ BufferedReaderTest.test_constructor(self) BufferedWriterTest.test_constructor(self) + def test_uninitialized(self): + BufferedReaderTest.test_uninitialized(self) + BufferedWriterTest.test_uninitialized(self) + def test_read_and_write(self): raw = self.MockRawIO((b"asdf", b"ghjk")) rw = self.tp(raw, 8) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -20,6 +20,9 @@ Library ------- +- Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. + Based on patch by Stephen Tu. + - Issue #20594: Avoid name clash with the libc function posix_close. - Issue #19856: shutil.move() failed to move a directory to other directory diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -2263,9 +2263,14 @@ static PyObject * _forward_call(buffered *self, _Py_Identifier *name, PyObject *args) { - PyObject *func = _PyObject_GetAttrId((PyObject *)self, name); - PyObject *ret; + PyObject *func, *ret; + if (self == NULL) { + PyErr_SetString(PyExc_ValueError, + "I/O operation on uninitialized object"); + return NULL; + } + func = _PyObject_GetAttrId((PyObject *)self, name); if (func == NULL) { PyErr_SetString(PyExc_AttributeError, name->string); return NULL; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 09:55:42 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 12 Feb 2014 09:55:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2317671=3A_Fixed_a_crash_when_use_non-initialized?= =?utf-8?q?_io=2EBufferedRWPair=2E?= Message-ID: <3fPF7L392Xz7LkW@mail.python.org> http://hg.python.org/cpython/rev/f003ef13c555 changeset: 89169:f003ef13c555 parent: 89166:efaf12106d68 parent: 89168:25ff4625680d user: Serhiy Storchaka date: Wed Feb 12 10:55:07 2014 +0200 summary: Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. Based on patch by Stephen Tu. files: Lib/test/test_io.py | 38 ++++++++++++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_io/bufferedio.c | 9 +++++- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -855,6 +855,16 @@ bufio.__init__(rawio) self.assertEqual(b"abc", bufio.read()) + def test_uninitialized(self): + bufio = self.tp.__new__(self.tp) + del bufio + bufio = self.tp.__new__(self.tp) + self.assertRaisesRegex((ValueError, AttributeError), + 'uninitialized|has no attribute', + bufio.read, 0) + bufio.__init__(self.MockRawIO()) + self.assertEqual(bufio.read(0), b'') + def test_read(self): for arg in (None, 7): rawio = self.MockRawIO((b"abc", b"d", b"efg")) @@ -1106,6 +1116,16 @@ bufio.flush() self.assertEqual(b"".join(rawio._write_stack), b"abcghi") + def test_uninitialized(self): + bufio = self.tp.__new__(self.tp) + del bufio + bufio = self.tp.__new__(self.tp) + self.assertRaisesRegex((ValueError, AttributeError), + 'uninitialized|has no attribute', + bufio.write, b'') + bufio.__init__(self.MockRawIO()) + self.assertEqual(bufio.write(b''), 0) + def test_detach_flush(self): raw = self.MockRawIO() buf = self.tp(raw) @@ -1390,6 +1410,20 @@ pair = self.tp(self.MockRawIO(), self.MockRawIO()) self.assertFalse(pair.closed) + def test_uninitialized(self): + pair = self.tp.__new__(self.tp) + del pair + pair = self.tp.__new__(self.tp) + self.assertRaisesRegex((ValueError, AttributeError), + 'uninitialized|has no attribute', + pair.read, 0) + self.assertRaisesRegex((ValueError, AttributeError), + 'uninitialized|has no attribute', + pair.write, b'') + pair.__init__(self.MockRawIO(), self.MockRawIO()) + self.assertEqual(pair.read(0), b'') + self.assertEqual(pair.write(b''), 0) + def test_detach(self): pair = self.tp(self.MockRawIO(), self.MockRawIO()) self.assertRaises(self.UnsupportedOperation, pair.detach) @@ -1516,6 +1550,10 @@ BufferedReaderTest.test_constructor(self) BufferedWriterTest.test_constructor(self) + def test_uninitialized(self): + BufferedReaderTest.test_uninitialized(self) + BufferedWriterTest.test_uninitialized(self) + def test_read_and_write(self): raw = self.MockRawIO((b"asdf", b"ghjk")) rw = self.tp(raw, 8) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Library ------- +- Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. + Based on patch by Stephen Tu. + - Issue #20594: Avoid name clash with the libc function posix_close. - Issue #19856: shutil.move() failed to move a directory to other directory diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -2305,9 +2305,14 @@ static PyObject * _forward_call(buffered *self, _Py_Identifier *name, PyObject *args) { - PyObject *func = _PyObject_GetAttrId((PyObject *)self, name); - PyObject *ret; + PyObject *func, *ret; + if (self == NULL) { + PyErr_SetString(PyExc_ValueError, + "I/O operation on uninitialized object"); + return NULL; + } + func = _PyObject_GetAttrId((PyObject *)self, name); if (func == NULL) { PyErr_SetString(PyExc_AttributeError, name->string); return NULL; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 11:40:50 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 12 Feb 2014 11:40:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Try_to_fix_test=5Fcleanup_?= =?utf-8?b?KGlzc3VlICMyMDU5OSku?= Message-ID: <3fPHSf2vY3z7Ljj@mail.python.org> http://hg.python.org/cpython/rev/7ecee9e0dc58 changeset: 89170:7ecee9e0dc58 user: Serhiy Storchaka date: Wed Feb 12 12:40:22 2014 +0200 summary: Try to fix test_cleanup (issue #20599). files: Lib/test/test_builtin.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1604,10 +1604,10 @@ class C: def __del__(self): - print("before") + print("before", flush=True) # Check that builtins still exist len(()) - print("after") + print("after", flush=True) c = C() # Make this module survive until builtins and sys are cleaned -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 18:28:59 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 12 Feb 2014 18:28:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320599=3A_Force_AS?= =?utf-8?q?CII_encoding_for_stdout_in_test=5Fcleanup=28=29_of_test=5Fbuilt?= =?utf-8?q?in?= Message-ID: <3fPSWb46Tjz7LjN@mail.python.org> http://hg.python.org/cpython/rev/10ea3125d7b8 changeset: 89171:10ea3125d7b8 user: Victor Stinner date: Wed Feb 12 18:27:55 2014 +0100 summary: Issue #20599: Force ASCII encoding for stdout in test_cleanup() of test_builtin On Windows, the codec of sys.stdout is implemented in Python. At exit, the codec may be unloaded before the destructor tries to write something to sys.stdout. files: Lib/test/test_builtin.py | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1604,10 +1604,10 @@ class C: def __del__(self): - print("before", flush=True) + print("before") # Check that builtins still exist len(()) - print("after", flush=True) + print("after") c = C() # Make this module survive until builtins and sys are cleaned @@ -1617,7 +1617,15 @@ # through a GC phase. here = sys.modules[__name__] """ - rc, out, err = assert_python_ok("-c", code) + # Issue #20599: Force ASCII encoding to get a codec implemented in C, + # otherwise the codec may be unloaded before C.__del__() is called, and + # so print("before") fails because the codec cannot be used to encode + # "before" to sys.stdout.encoding. For example, on Windows, + # sys.stdout.encoding is the OEM code page and these code pages are + # implemented in Python + rc, out, err = assert_python_ok("-c", code, + PYTHONIOENCODING="ascii", + __cleanenv=True) self.assertEqual(["before", "after"], out.decode().splitlines()) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 19:01:06 2014 From: python-checkins at python.org (r.david.murray) Date: Wed, 12 Feb 2014 19:01:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_LOAD=5FCLASSDE?= =?utf-8?q?REF=2C_-X_showrefcount?= Message-ID: <3fPTDf2g4Hz7Lqt@mail.python.org> http://hg.python.org/cpython/rev/b18d4b6ccdc7 changeset: 89172:b18d4b6ccdc7 user: R David Murray date: Wed Feb 12 13:00:36 2014 -0500 summary: whatsnew: LOAD_CLASSDEREF, -X showrefcount files: Doc/reference/datamodel.rst | 2 ++ Doc/whatsnew/3.4.rst | 8 ++++++++ 2 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1647,6 +1647,8 @@ that criterion, then the class definition will fail with ``TypeError``. +.. _prepare: + Preparing the class namespace ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1455,6 +1455,10 @@ now works correctly (previously it silently returned the first python module in the file). (Contributed by V?clav ?milauer in :issue:`16421`.) +* A new opcode, :opcode:`LOAD_CLASSDEREF`, has been added to fix a bug in the + loading of free variables in class bodies that could be triggered by certain + uses of :ref:`__prepare__ `. (Contributed by Benjamin Peterson in + :issue:`17853`.) Significant Optimizations @@ -1650,6 +1654,10 @@ how :envvar:`PATH` works. The behavior now conforms to the posix convention for :envvar:`PATH`. +* The [X refs, Y blocks] output of a debug (``--with-pydebug``) build of the + CPython interpreter is now off by default. It can be re-enabled using the + ``-X showrefcount`` option. (Contributed by Ezio Melotti in :issue:`17323`.) + Changes in the Python API ------------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 19:42:00 2014 From: python-checkins at python.org (r.david.murray) Date: Wed, 12 Feb 2014 19:42:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_PyUnicode=5FFr?= =?utf-8?q?omFormat_width/precision=2C_thread_cleanup_after_fork=2E?= Message-ID: <3fPV7r0Xylz7LjN@mail.python.org> http://hg.python.org/cpython/rev/3d171a26574b changeset: 89173:3d171a26574b user: R David Murray date: Wed Feb 12 13:39:11 2014 -0500 summary: whatsnew: PyUnicode_FromFormat width/precision, thread cleanup after fork. files: Doc/whatsnew/3.4.rst | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1416,6 +1416,10 @@ * New shell version of ``python-config``; can be used even when a python interpreter is not available (for example, in cross compilation scenarios). +* :c:func:`PyUnicode_FromFormat` now supports width and precision + specifications for ``%s``, ``%A``, ``%U``, ``%V``, ``%S``, and ``%R``. + (Contributed by Ysj Ray and Victor Stinner in :issue:`7330`.) + Other Improvements @@ -1671,7 +1675,7 @@ * The module type now initializes the :attr:`__package__` and :attr:`__loader__` attributes to ``None`` by default. To determine if these attributes were set in a backwards-compatible fashion, use e.g. - ``getattr(module, '__loader__', None) is not None``. + ``getattr(module, '__loader__', None) is not None``. (:issue:`17115`.) * :meth:`importlib.util.module_for_loader` now sets ``__loader__`` and ``__package__`` unconditionally to properly support reloading. If this is not @@ -1772,6 +1776,11 @@ regular keyword arguments, instead of before. Hopefully no one wrote any code that depends on the previous buggy behavior (:issue:`16967`). +* Stale thread states are now cleared after :func:`~os.fork`. This may cause + some system resources to be released that previously were incorrectly kept + perpetually alive (for example, database connections kept in thread-local + storage). (:issue:`17094`.) + Changes in the C API -------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 19:42:01 2014 From: python-checkins at python.org (r.david.murray) Date: Wed, 12 Feb 2014 19:42:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_=27other_impro?= =?utf-8?q?vements=27_and_=27optimizations=27_belong_under_CPython_heading?= =?utf-8?q?=2E?= Message-ID: <3fPV7s2vgBz7LjN@mail.python.org> http://hg.python.org/cpython/rev/c1d20c017fc3 changeset: 89174:c1d20c017fc3 user: R David Murray date: Wed Feb 12 13:41:01 2014 -0500 summary: whatsnew: 'other improvements' and 'optimizations' belong under CPython heading. files: Doc/whatsnew/3.4.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1423,7 +1423,7 @@ Other Improvements -================== +------------------ * Tab-completion is now enabled by default in the interactive interpreter. (Contributed by Antoine Pitrou and ?ric Araujo in :issue:`5845`.) @@ -1466,7 +1466,7 @@ Significant Optimizations -========================= +------------------------- * The UTF-32 decoder is now 3x to 4x faster. (Contributed by Serhiy Storchaka in :issue:`14625`.) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 12 23:02:19 2014 From: python-checkins at python.org (yury.selivanov) Date: Wed, 12 Feb 2014 23:02:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Eevents=3A_Use_?= =?utf-8?q?=5F=5Fslots=5F=5F_in_Handle_and_TimerHandle?= Message-ID: <3fPZZz2sJyz7LjR@mail.python.org> http://hg.python.org/cpython/rev/920304e1f36b changeset: 89175:920304e1f36b user: Yury Selivanov date: Wed Feb 12 17:01:52 2014 -0500 summary: asyncio.events: Use __slots__ in Handle and TimerHandle files: Lib/asyncio/events.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -19,6 +19,8 @@ class Handle: """Object returned by callback registration methods.""" + __slots__ = ['_callback', '_args', '_cancelled'] + def __init__(self, callback, args): assert not isinstance(callback, Handle), 'A Handle is not a callback' self._callback = callback @@ -46,6 +48,8 @@ class TimerHandle(Handle): """Object returned by timed callback registration methods.""" + __slots__ = ['_when'] + def __init__(self, when, callback, args): assert when is not None super().__init__(callback, args) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 13 02:58:31 2014 From: python-checkins at python.org (guido.van.rossum) Date: Thu, 13 Feb 2014 02:58:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Change_as=5Fcom?= =?utf-8?q?pleted=28=29_to_use_a_Queue=2C_to_avoid_O=28N**2=29_behavior=2E?= =?utf-8?q?_Fixes?= Message-ID: <3fPgqW486Xz7LjP@mail.python.org> http://hg.python.org/cpython/rev/6e04027ed53e changeset: 89176:6e04027ed53e user: Guido van Rossum date: Wed Feb 12 17:58:19 2014 -0800 summary: asyncio: Change as_completed() to use a Queue, to avoid O(N**2) behavior. Fixes issue #20566. files: Lib/asyncio/tasks.py | 53 ++++++++++------ Lib/test/test_asyncio/test_tasks.py | 23 +++++++- 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -463,7 +463,11 @@ # This is *not* a @coroutine! It is just an iterator (yielding Futures). def as_completed(fs, *, loop=None, timeout=None): - """Return an iterator whose values, when waited for, are Futures. + """Return an iterator whose values are coroutines. + + When waiting for the yielded coroutines you'll get the results (or + exceptions!) of the original Futures (or coroutines), in the order + in which and as soon as they complete. This differs from PEP 3148; the proper way to use this is: @@ -471,8 +475,8 @@ result = yield from f # The 'yield from' may raise. # Use result. - Raises TimeoutError if the timeout occurs before all Futures are - done. + If a timeout is specified, the 'yield from' will raise + TimeoutError when the timeout occurs before all Futures are done. Note: The futures 'f' are not necessarily members of fs. """ @@ -481,27 +485,36 @@ loop = loop if loop is not None else events.get_event_loop() deadline = None if timeout is None else loop.time() + timeout todo = {async(f, loop=loop) for f in set(fs)} - completed = collections.deque() + from .queues import Queue # Import here to avoid circular import problem. + done = Queue(loop=loop) + timeout_handle = None + + def _on_timeout(): + for f in todo: + f.remove_done_callback(_on_completion) + done.put_nowait(None) # Queue a dummy value for _wait_for_one(). + todo.clear() # Can't do todo.remove(f) in the loop. + + def _on_completion(f): + if not todo: + return # _on_timeout() was here first. + todo.remove(f) + done.put_nowait(f) + if not todo and timeout_handle is not None: + timeout_handle.cancel() @coroutine def _wait_for_one(): - while not completed: - timeout = None - if deadline is not None: - timeout = deadline - loop.time() - if timeout < 0: - raise futures.TimeoutError() - done, pending = yield from _wait( - todo, timeout, FIRST_COMPLETED, loop) - # Multiple callers might be waiting for the same events - # and getting the same outcome. Dedupe by updating todo. - for f in done: - if f in todo: - todo.remove(f) - completed.append(f) - f = completed.popleft() - return f.result() # May raise. + f = yield from done.get() + if f is None: + # Dummy value from _on_timeout(). + raise futures.TimeoutError + return f.result() # May raise f.exception(). + for f in todo: + f.add_done_callback(_on_completion) + if todo and timeout is not None: + timeout_handle = loop.call_later(timeout, _on_timeout) for _ in range(len(todo)): yield _wait_for_one() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -779,7 +779,6 @@ yield 0 yield 0 yield 0.1 - yield 0.02 loop = test_utils.TestLoop(gen) self.addCleanup(loop.close) @@ -791,6 +790,8 @@ 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 values.append((1, v)) @@ -809,6 +810,26 @@ loop.advance_time(10) loop.run_until_complete(asyncio.wait([a, b], loop=loop)) + def test_as_completed_with_unused_timeout(self): + + def gen(): + yield + yield 0 + yield 0.01 + + loop = test_utils.TestLoop(gen) + self.addCleanup(loop.close) + + a = asyncio.sleep(0.01, 'a', loop=loop) + + @asyncio.coroutine + def foo(): + for f in asyncio.as_completed([a], timeout=1, loop=loop): + v = yield from f + self.assertEqual(v, 'a') + + res = loop.run_until_complete(asyncio.Task(foo(), loop=loop)) + def test_as_completed_reverse_wait(self): def gen(): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 13 09:16:45 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 13 Feb 2014 09:16:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzY4MTU6?= =?utf-8?q?_os=2Epath=2Eexpandvars=28=29_now_supports_non-ASCII_environmen?= =?utf-8?q?t?= Message-ID: <3fPrCx3d1Xz7LjS@mail.python.org> http://hg.python.org/cpython/rev/08746e015c64 changeset: 89177:08746e015c64 branch: 3.3 parent: 89168:25ff4625680d user: Serhiy Storchaka date: Thu Feb 13 10:13:53 2014 +0200 summary: Issue #6815: os.path.expandvars() now supports non-ASCII environment variables names and values. files: Lib/ntpath.py | 60 ++++++++++++----------- Lib/posixpath.py | 18 ++++--- Lib/test/test_genericpath.py | 30 +++++++++++- Lib/test/test_ntpath.py | 27 +++++++++- Misc/NEWS | 3 + 5 files changed, 96 insertions(+), 42 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -362,6 +362,7 @@ percent = b'%' brace = b'{' dollar = b'$' + environ = getattr(os, 'environb', None) else: if '$' not in path and '%' not in path: return path @@ -371,6 +372,7 @@ percent = '%' brace = '{' dollar = '$' + environ = os.environ res = path[:0] index = 0 pathlen = len(path) @@ -399,14 +401,13 @@ index = pathlen - 1 else: var = path[:index] - if isinstance(path, bytes): - var = var.decode('ascii') - if var in os.environ: - value = os.environ[var] - else: - value = '%' + var + '%' - if isinstance(path, bytes): - value = value.encode('ascii') + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[var] + except KeyError: + value = percent + var + percent res += value elif c == dollar: # variable or '$$' if path[index + 1:index + 2] == dollar: @@ -420,39 +421,40 @@ index = path.index(b'}') else: index = path.index('}') - var = path[:index] - if isinstance(path, bytes): - var = var.decode('ascii') - if var in os.environ: - value = os.environ[var] - else: - value = '${' + var + '}' - if isinstance(path, bytes): - value = value.encode('ascii') - res += value except ValueError: if isinstance(path, bytes): res += b'${' + path else: res += '${' + path index = pathlen - 1 + else: + var = path[:index] + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[var] + except KeyError: + if isinstance(path, bytes): + value = b'${' + var + b'}' + else: + value = '${' + var + '}' + res += value else: - var = '' + var = path[:0] index += 1 c = path[index:index + 1] while c and c in varchars: - if isinstance(path, bytes): - var += c.decode('ascii') - else: - var += c + var += c index += 1 c = path[index:index + 1] - if var in os.environ: - value = os.environ[var] - else: - value = '$' + var - if isinstance(path, bytes): - value = value.encode('ascii') + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[var] + except KeyError: + value = dollar + var res += value if c: index -= 1 diff --git a/Lib/posixpath.py b/Lib/posixpath.py --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -300,6 +300,7 @@ search = _varprogb.search start = b'{' end = b'}' + environ = getattr(os, 'environb', None) else: if '$' not in path: return path @@ -309,6 +310,7 @@ search = _varprog.search start = '{' end = '}' + environ = os.environ i = 0 while True: m = search(path, i) @@ -318,18 +320,18 @@ name = m.group(1) if name.startswith(start) and name.endswith(end): name = name[1:-1] - if isinstance(name, bytes): - name = str(name, 'ASCII') - if name in os.environ: + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[name] + except KeyError: + i = j + else: tail = path[j:] - value = os.environ[name] - if isinstance(path, bytes): - value = value.encode('ASCII') path = path[:i] + value i = len(path) path += tail - else: - i = j return path diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -248,7 +248,6 @@ self.assertEqual(expandvars("$[foo]bar"), "$[foo]bar") self.assertEqual(expandvars("$bar bar"), "$bar bar") self.assertEqual(expandvars("$?bar"), "$?bar") - self.assertEqual(expandvars("${foo}bar"), "barbar") self.assertEqual(expandvars("$foo}bar"), "bar}bar") self.assertEqual(expandvars("${foo"), "${foo") self.assertEqual(expandvars("${{foo}}"), "baz1}") @@ -261,13 +260,40 @@ self.assertEqual(expandvars(b"$[foo]bar"), b"$[foo]bar") self.assertEqual(expandvars(b"$bar bar"), b"$bar bar") self.assertEqual(expandvars(b"$?bar"), b"$?bar") - self.assertEqual(expandvars(b"${foo}bar"), b"barbar") self.assertEqual(expandvars(b"$foo}bar"), b"bar}bar") self.assertEqual(expandvars(b"${foo"), b"${foo") self.assertEqual(expandvars(b"${{foo}}"), b"baz1}") self.assertEqual(expandvars(b"$foo$foo"), b"barbar") self.assertEqual(expandvars(b"$bar$bar"), b"$bar$bar") + @unittest.skipUnless(support.FS_NONASCII, 'need support.FS_NONASCII') + def test_expandvars_nonascii(self): + if self.pathmodule.__name__ == 'macpath': + self.skipTest('macpath.expandvars is a stub') + expandvars = self.pathmodule.expandvars + def check(value, expected): + self.assertEqual(expandvars(value), expected) + with support.EnvironmentVarGuard() as env: + env.clear() + nonascii = support.FS_NONASCII + env['spam'] = nonascii + env[nonascii] = 'ham' + nonascii + check(nonascii, nonascii) + check('$spam bar', '%s bar' % nonascii) + check('${spam}bar', '%sbar' % nonascii) + check('${%s}bar' % nonascii, 'ham%sbar' % nonascii) + check('$bar%s bar' % nonascii, '$bar%s bar' % nonascii) + check('$spam}bar', '%s}bar' % nonascii) + + check(os.fsencode(nonascii), os.fsencode(nonascii)) + check(b'$spam bar', os.fsencode('%s bar' % nonascii)) + check(b'${spam}bar', os.fsencode('%sbar' % nonascii)) + check(os.fsencode('${%s}bar' % nonascii), + os.fsencode('ham%sbar' % nonascii)) + check(os.fsencode('$bar%s bar' % nonascii), + os.fsencode('$bar%s bar' % nonascii)) + check(b'$spam}bar', os.fsencode('%s}bar' % nonascii)) + def test_abspath(self): self.assertIn("foo", self.pathmodule.abspath("foo")) with warnings.catch_warnings(): diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -22,13 +22,15 @@ fn = fn.replace('["', '[b"') fn = fn.replace(", '", ", b'") fn = fn.replace(', "', ', b"') + fn = os.fsencode(fn).decode('latin1') + fn = fn.encode('ascii', 'backslashreplace').decode('ascii') with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) gotResult = eval(fn) if isinstance(wantResult, str): - wantResult = wantResult.encode('ascii') + wantResult = os.fsencode(wantResult) elif isinstance(wantResult, tuple): - wantResult = tuple(r.encode('ascii') for r in wantResult) + wantResult = tuple(os.fsencode(r) for r in wantResult) gotResult = eval(fn) if wantResult != gotResult: @@ -223,7 +225,6 @@ tester('ntpath.expandvars("$[foo]bar")', "$[foo]bar") tester('ntpath.expandvars("$bar bar")', "$bar bar") tester('ntpath.expandvars("$?bar")', "$?bar") - tester('ntpath.expandvars("${foo}bar")', "barbar") tester('ntpath.expandvars("$foo}bar")', "bar}bar") tester('ntpath.expandvars("${foo")', "${foo") tester('ntpath.expandvars("${{foo}}")', "baz1}") @@ -237,6 +238,26 @@ tester('ntpath.expandvars("%foo%%bar")', "bar%bar") tester('ntpath.expandvars("\'%foo%\'%bar")', "\'%foo%\'%bar") + @unittest.skipUnless(support.FS_NONASCII, 'need support.FS_NONASCII') + def test_expandvars_nonascii(self): + def check(value, expected): + tester('ntpath.expandvars(%r)' % value, expected) + with support.EnvironmentVarGuard() as env: + env.clear() + nonascii = support.FS_NONASCII + env['spam'] = nonascii + env[nonascii] = 'ham' + nonascii + check('$spam bar', '%s bar' % nonascii) + check('$%s bar' % nonascii, '$%s bar' % nonascii) + check('${spam}bar', '%sbar' % nonascii) + check('${%s}bar' % nonascii, 'ham%sbar' % nonascii) + check('$spam}bar', '%s}bar' % nonascii) + check('$%s}bar' % nonascii, '$%s}bar' % nonascii) + check('%spam% bar', '%s bar' % nonascii) + check('%{}% bar'.format(nonascii), 'ham%s bar' % nonascii) + check('%spam%bar', '%sbar' % nonascii) + check('%{}%bar'.format(nonascii), 'ham%sbar' % nonascii) + def test_abspath(self): # ntpath.abspath() can only be used on a system with the "nt" module # (reasonably), so we protect this test with "import nt". This allows diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -20,6 +20,9 @@ Library ------- +- Issue #6815: os.path.expandvars() now supports non-ASCII environment + variables names and values. + - Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. Based on patch by Stephen Tu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 13 09:16:46 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 13 Feb 2014 09:16:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=236815=3A_os=2Epath=2Eexpandvars=28=29_now_suppor?= =?utf-8?q?ts_non-ASCII_environment?= Message-ID: <3fPrCy6ZQwz7LkF@mail.python.org> http://hg.python.org/cpython/rev/f3c146036e7c changeset: 89178:f3c146036e7c parent: 89176:6e04027ed53e parent: 89177:08746e015c64 user: Serhiy Storchaka date: Thu Feb 13 10:14:48 2014 +0200 summary: Issue #6815: os.path.expandvars() now supports non-ASCII environment variables names and values. files: Lib/ntpath.py | 60 ++++++++++++----------- Lib/posixpath.py | 18 ++++--- Lib/test/test_genericpath.py | 30 +++++++++++- Lib/test/test_ntpath.py | 27 +++++++++- Misc/NEWS | 3 + 5 files changed, 96 insertions(+), 42 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -377,6 +377,7 @@ percent = b'%' brace = b'{' dollar = b'$' + environ = getattr(os, 'environb', None) else: if '$' not in path and '%' not in path: return path @@ -386,6 +387,7 @@ percent = '%' brace = '{' dollar = '$' + environ = os.environ res = path[:0] index = 0 pathlen = len(path) @@ -414,14 +416,13 @@ index = pathlen - 1 else: var = path[:index] - if isinstance(path, bytes): - var = var.decode('ascii') - if var in os.environ: - value = os.environ[var] - else: - value = '%' + var + '%' - if isinstance(path, bytes): - value = value.encode('ascii') + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[var] + except KeyError: + value = percent + var + percent res += value elif c == dollar: # variable or '$$' if path[index + 1:index + 2] == dollar: @@ -435,39 +436,40 @@ index = path.index(b'}') else: index = path.index('}') - var = path[:index] - if isinstance(path, bytes): - var = var.decode('ascii') - if var in os.environ: - value = os.environ[var] - else: - value = '${' + var + '}' - if isinstance(path, bytes): - value = value.encode('ascii') - res += value except ValueError: if isinstance(path, bytes): res += b'${' + path else: res += '${' + path index = pathlen - 1 + else: + var = path[:index] + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[var] + except KeyError: + if isinstance(path, bytes): + value = b'${' + var + b'}' + else: + value = '${' + var + '}' + res += value else: - var = '' + var = path[:0] index += 1 c = path[index:index + 1] while c and c in varchars: - if isinstance(path, bytes): - var += c.decode('ascii') - else: - var += c + var += c index += 1 c = path[index:index + 1] - if var in os.environ: - value = os.environ[var] - else: - value = '$' + var - if isinstance(path, bytes): - value = value.encode('ascii') + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[var] + except KeyError: + value = dollar + var res += value if c: index -= 1 diff --git a/Lib/posixpath.py b/Lib/posixpath.py --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -279,6 +279,7 @@ search = _varprogb.search start = b'{' end = b'}' + environ = getattr(os, 'environb', None) else: if '$' not in path: return path @@ -288,6 +289,7 @@ search = _varprog.search start = '{' end = '}' + environ = os.environ i = 0 while True: m = search(path, i) @@ -297,18 +299,18 @@ name = m.group(1) if name.startswith(start) and name.endswith(end): name = name[1:-1] - if isinstance(name, bytes): - name = str(name, 'ASCII') - if name in os.environ: + try: + if environ is None: + value = os.fsencode(os.environ[os.fsdecode(var)]) + else: + value = environ[name] + except KeyError: + i = j + else: tail = path[j:] - value = os.environ[name] - if isinstance(path, bytes): - value = value.encode('ASCII') path = path[:i] + value i = len(path) path += tail - else: - i = j return path diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -329,7 +329,6 @@ self.assertEqual(expandvars("$[foo]bar"), "$[foo]bar") self.assertEqual(expandvars("$bar bar"), "$bar bar") self.assertEqual(expandvars("$?bar"), "$?bar") - self.assertEqual(expandvars("${foo}bar"), "barbar") self.assertEqual(expandvars("$foo}bar"), "bar}bar") self.assertEqual(expandvars("${foo"), "${foo") self.assertEqual(expandvars("${{foo}}"), "baz1}") @@ -342,13 +341,40 @@ self.assertEqual(expandvars(b"$[foo]bar"), b"$[foo]bar") self.assertEqual(expandvars(b"$bar bar"), b"$bar bar") self.assertEqual(expandvars(b"$?bar"), b"$?bar") - self.assertEqual(expandvars(b"${foo}bar"), b"barbar") self.assertEqual(expandvars(b"$foo}bar"), b"bar}bar") self.assertEqual(expandvars(b"${foo"), b"${foo") self.assertEqual(expandvars(b"${{foo}}"), b"baz1}") self.assertEqual(expandvars(b"$foo$foo"), b"barbar") self.assertEqual(expandvars(b"$bar$bar"), b"$bar$bar") + @unittest.skipUnless(support.FS_NONASCII, 'need support.FS_NONASCII') + def test_expandvars_nonascii(self): + if self.pathmodule.__name__ == 'macpath': + self.skipTest('macpath.expandvars is a stub') + expandvars = self.pathmodule.expandvars + def check(value, expected): + self.assertEqual(expandvars(value), expected) + with support.EnvironmentVarGuard() as env: + env.clear() + nonascii = support.FS_NONASCII + env['spam'] = nonascii + env[nonascii] = 'ham' + nonascii + check(nonascii, nonascii) + check('$spam bar', '%s bar' % nonascii) + check('${spam}bar', '%sbar' % nonascii) + check('${%s}bar' % nonascii, 'ham%sbar' % nonascii) + check('$bar%s bar' % nonascii, '$bar%s bar' % nonascii) + check('$spam}bar', '%s}bar' % nonascii) + + check(os.fsencode(nonascii), os.fsencode(nonascii)) + check(b'$spam bar', os.fsencode('%s bar' % nonascii)) + check(b'${spam}bar', os.fsencode('%sbar' % nonascii)) + check(os.fsencode('${%s}bar' % nonascii), + os.fsencode('ham%sbar' % nonascii)) + check(os.fsencode('$bar%s bar' % nonascii), + os.fsencode('$bar%s bar' % nonascii)) + check(b'$spam}bar', os.fsencode('%s}bar' % nonascii)) + def test_abspath(self): self.assertIn("foo", self.pathmodule.abspath("foo")) with warnings.catch_warnings(): diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -22,13 +22,15 @@ fn = fn.replace('["', '[b"') fn = fn.replace(", '", ", b'") fn = fn.replace(', "', ', b"') + fn = os.fsencode(fn).decode('latin1') + fn = fn.encode('ascii', 'backslashreplace').decode('ascii') with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) gotResult = eval(fn) if isinstance(wantResult, str): - wantResult = wantResult.encode('ascii') + wantResult = os.fsencode(wantResult) elif isinstance(wantResult, tuple): - wantResult = tuple(r.encode('ascii') for r in wantResult) + wantResult = tuple(os.fsencode(r) for r in wantResult) gotResult = eval(fn) if wantResult != gotResult: @@ -223,7 +225,6 @@ tester('ntpath.expandvars("$[foo]bar")', "$[foo]bar") tester('ntpath.expandvars("$bar bar")', "$bar bar") tester('ntpath.expandvars("$?bar")', "$?bar") - tester('ntpath.expandvars("${foo}bar")', "barbar") tester('ntpath.expandvars("$foo}bar")', "bar}bar") tester('ntpath.expandvars("${foo")', "${foo") tester('ntpath.expandvars("${{foo}}")', "baz1}") @@ -237,6 +238,26 @@ tester('ntpath.expandvars("%foo%%bar")', "bar%bar") tester('ntpath.expandvars("\'%foo%\'%bar")', "\'%foo%\'%bar") + @unittest.skipUnless(support.FS_NONASCII, 'need support.FS_NONASCII') + def test_expandvars_nonascii(self): + def check(value, expected): + tester('ntpath.expandvars(%r)' % value, expected) + with support.EnvironmentVarGuard() as env: + env.clear() + nonascii = support.FS_NONASCII + env['spam'] = nonascii + env[nonascii] = 'ham' + nonascii + check('$spam bar', '%s bar' % nonascii) + check('$%s bar' % nonascii, '$%s bar' % nonascii) + check('${spam}bar', '%sbar' % nonascii) + check('${%s}bar' % nonascii, 'ham%sbar' % nonascii) + check('$spam}bar', '%s}bar' % nonascii) + check('$%s}bar' % nonascii, '$%s}bar' % nonascii) + check('%spam% bar', '%s bar' % nonascii) + check('%{}% bar'.format(nonascii), 'ham%s bar' % nonascii) + check('%spam%bar', '%sbar' % nonascii) + check('%{}%bar'.format(nonascii), 'ham%sbar' % nonascii) + def test_abspath(self): # ntpath.abspath() can only be used on a system with the "nt" module # (reasonably), so we protect this test with "import nt". This allows diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Library ------- +- Issue #6815: os.path.expandvars() now supports non-ASCII environment + variables names and values. + - Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. Based on patch by Stephen Tu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 13 09:25:18 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 13 Feb 2014 09:25:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_ayncio=2C_Tulip_issue_129?= =?utf-8?q?=3A_BaseEventLoop=2Esock=5Fconnect=28=29_now_raises_an_error_if?= Message-ID: <3fPrPp5VnRz7LjS@mail.python.org> http://hg.python.org/cpython/rev/95de14f53cf5 changeset: 89179:95de14f53cf5 user: Victor Stinner date: Thu Feb 13 09:24:37 2014 +0100 summary: ayncio, Tulip issue 129: BaseEventLoop.sock_connect() now raises an error if the address is not resolved (hostname instead of an IP address) for AF_INET and AF_INET6 address families. files: Doc/library/asyncio-eventloop.rst | 6 +++ Lib/asyncio/base_events.py | 25 ++++++++++++++++ Lib/asyncio/proactor_events.py | 9 +++++- Lib/asyncio/selector_events.py | 20 +++++------- Lib/test/test_asyncio/test_events.py | 12 +++++++ 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -366,6 +366,12 @@ Connect to a remote socket at *address*. + The *address* must be already resolved to avoid the trap of hanging the + entire event loop when the address requires doing a DNS lookup. For + example, it must be an IP address, not an hostname, for + :py:data:`~socket.AF_INET` and :py:data:`~socket.AF_INET6` address families. + Use :meth:`getaddrinfo` to resolve the hostname asynchronously. + This method returns a :ref:`coroutine object `. .. seealso:: diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -41,6 +41,31 @@ """Raised to stop the event loop.""" +def _check_resolved_address(sock, address): + # Ensure that the address is already resolved to avoid the trap of hanging + # the entire event loop when the address requires doing a DNS lookup. + family = sock.family + if family not in (socket.AF_INET, socket.AF_INET6): + return + + host, port = address + type_mask = 0 + if hasattr(socket, 'SOCK_NONBLOCK'): + type_mask |= socket.SOCK_NONBLOCK + if hasattr(socket, 'SOCK_CLOEXEC'): + type_mask |= socket.SOCK_CLOEXEC + # Use getaddrinfo(AI_NUMERICHOST) to ensure that the address is + # already resolved. + try: + socket.getaddrinfo(host, port, + family=family, + type=(sock.type & ~type_mask), + proto=sock.proto, + flags=socket.AI_NUMERICHOST) + except socket.gaierror as err: + raise ValueError("address must be resolved (IP address), got %r: %s" + % (address, err)) + def _raise_stop_error(*args): raise _StopError diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -404,7 +404,14 @@ return self._proactor.send(sock, data) def sock_connect(self, sock, address): - return self._proactor.connect(sock, address) + try: + base_events._check_resolved_address(sock, address) + except ValueError as err: + fut = futures.Future(loop=self) + fut.set_exception(err) + return fut + else: + return self._proactor.connect(sock, address) def sock_accept(self, sock): return self._proactor.accept(sock) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -208,6 +208,8 @@ return fut def _sock_recv(self, fut, registered, sock, n): + # _sock_recv() can add itself as an I/O callback if the operation can't + # be done immediatly. Don't use it directly, call sock_recv(). fd = sock.fileno() if registered: # Remove the callback early. It should be rare that the @@ -260,22 +262,16 @@ def sock_connect(self, sock, address): """XXX""" - # That address better not require a lookup! We're not calling - # self.getaddrinfo() for you here. But verifying this is - # complicated; the socket module doesn't have a pattern for - # IPv6 addresses (there are too many forms, apparently). fut = futures.Future(loop=self) - self._sock_connect(fut, False, sock, address) + try: + base_events._check_resolved_address(sock, address) + except ValueError as err: + fut.set_exception(err) + else: + self._sock_connect(fut, False, sock, address) return fut def _sock_connect(self, fut, registered, sock, address): - # TODO: Use getaddrinfo() to look up the address, to avoid the - # trap of hanging the entire event loop when the address - # requires doing a DNS lookup. (OTOH, the caller should - # already have done this, so it would be nice if we could - # easily tell whether the address needs looking up or not. I - # know how to do this for IPv4, but IPv6 addresses have many - # syntaxes.) fd = sock.fileno() if registered: self.remove_writer(fd) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1191,6 +1191,18 @@ {'clock_resolution': self.loop._clock_resolution, 'selector': self.loop._selector.__class__.__name__}) + def test_sock_connect_address(self): + address = ('www.python.org', 80) + for family in (socket.AF_INET, socket.AF_INET6): + for sock_type in (socket.SOCK_STREAM, socket.SOCK_DGRAM): + sock = socket.socket(family, sock_type) + with sock: + connect = self.loop.sock_connect(sock, address) + with self.assertRaises(ValueError) as cm: + self.loop.run_until_complete(connect) + self.assertIn('address must be resolved', + str(cm.exception)) + class SubprocessTestsMixin: -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Feb 13 09:44:46 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 13 Feb 2014 09:44:46 +0100 Subject: [Python-checkins] Daily reference leaks (6e04027ed53e): sum=4 Message-ID: results for 6e04027ed53e on branch "default" -------------------------------------------- test_site leaked [0, 0, 2] references, sum=2 test_site leaked [0, 0, 2] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogToKlvZ', '-x'] From python-checkins at python.org Thu Feb 13 09:49:51 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 13 Feb 2014 09:49:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Fixed_typo_in_?= =?utf-8?q?previous_commit_=28issue_=236815=29=2E?= Message-ID: <3fPry74zVrz7LjP@mail.python.org> http://hg.python.org/cpython/rev/b5ad525076eb changeset: 89180:b5ad525076eb branch: 3.3 parent: 89177:08746e015c64 user: Serhiy Storchaka date: Thu Feb 13 10:45:14 2014 +0200 summary: Fixed typo in previous commit (issue #6815). files: Lib/posixpath.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/posixpath.py b/Lib/posixpath.py --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -322,7 +322,7 @@ name = name[1:-1] try: if environ is None: - value = os.fsencode(os.environ[os.fsdecode(var)]) + value = os.fsencode(os.environ[os.fsdecode(name)]) else: value = environ[name] except KeyError: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 13 09:49:52 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 13 Feb 2014 09:49:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Fixed_typo_in_previous_commit_=28issue_=236815=29=2E?= Message-ID: <3fPry86RVmz7LjY@mail.python.org> http://hg.python.org/cpython/rev/6825395e6107 changeset: 89181:6825395e6107 parent: 89178:f3c146036e7c parent: 89180:b5ad525076eb user: Serhiy Storchaka date: Thu Feb 13 10:45:48 2014 +0200 summary: Fixed typo in previous commit (issue #6815). files: Lib/posixpath.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/posixpath.py b/Lib/posixpath.py --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -301,7 +301,7 @@ name = name[1:-1] try: if environ is None: - value = os.fsencode(os.environ[os.fsdecode(var)]) + value = os.fsencode(os.environ[os.fsdecode(name)]) else: value = environ[name] except KeyError: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 13 09:49:54 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 13 Feb 2014 09:49:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_heads?= Message-ID: <3fPryB2Py7z7Ljs@mail.python.org> http://hg.python.org/cpython/rev/0f357cf011d3 changeset: 89182:0f357cf011d3 parent: 89181:6825395e6107 parent: 89179:95de14f53cf5 user: Serhiy Storchaka date: Thu Feb 13 10:49:30 2014 +0200 summary: Merge heads files: Doc/library/asyncio-eventloop.rst | 6 +++ Lib/asyncio/base_events.py | 25 ++++++++++++++++ Lib/asyncio/proactor_events.py | 9 +++++- Lib/asyncio/selector_events.py | 20 +++++------- Lib/test/test_asyncio/test_events.py | 12 +++++++ 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -366,6 +366,12 @@ Connect to a remote socket at *address*. + The *address* must be already resolved to avoid the trap of hanging the + entire event loop when the address requires doing a DNS lookup. For + example, it must be an IP address, not an hostname, for + :py:data:`~socket.AF_INET` and :py:data:`~socket.AF_INET6` address families. + Use :meth:`getaddrinfo` to resolve the hostname asynchronously. + This method returns a :ref:`coroutine object `. .. seealso:: diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -41,6 +41,31 @@ """Raised to stop the event loop.""" +def _check_resolved_address(sock, address): + # Ensure that the address is already resolved to avoid the trap of hanging + # the entire event loop when the address requires doing a DNS lookup. + family = sock.family + if family not in (socket.AF_INET, socket.AF_INET6): + return + + host, port = address + type_mask = 0 + if hasattr(socket, 'SOCK_NONBLOCK'): + type_mask |= socket.SOCK_NONBLOCK + if hasattr(socket, 'SOCK_CLOEXEC'): + type_mask |= socket.SOCK_CLOEXEC + # Use getaddrinfo(AI_NUMERICHOST) to ensure that the address is + # already resolved. + try: + socket.getaddrinfo(host, port, + family=family, + type=(sock.type & ~type_mask), + proto=sock.proto, + flags=socket.AI_NUMERICHOST) + except socket.gaierror as err: + raise ValueError("address must be resolved (IP address), got %r: %s" + % (address, err)) + def _raise_stop_error(*args): raise _StopError diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -404,7 +404,14 @@ return self._proactor.send(sock, data) def sock_connect(self, sock, address): - return self._proactor.connect(sock, address) + try: + base_events._check_resolved_address(sock, address) + except ValueError as err: + fut = futures.Future(loop=self) + fut.set_exception(err) + return fut + else: + return self._proactor.connect(sock, address) def sock_accept(self, sock): return self._proactor.accept(sock) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -208,6 +208,8 @@ return fut def _sock_recv(self, fut, registered, sock, n): + # _sock_recv() can add itself as an I/O callback if the operation can't + # be done immediatly. Don't use it directly, call sock_recv(). fd = sock.fileno() if registered: # Remove the callback early. It should be rare that the @@ -260,22 +262,16 @@ def sock_connect(self, sock, address): """XXX""" - # That address better not require a lookup! We're not calling - # self.getaddrinfo() for you here. But verifying this is - # complicated; the socket module doesn't have a pattern for - # IPv6 addresses (there are too many forms, apparently). fut = futures.Future(loop=self) - self._sock_connect(fut, False, sock, address) + try: + base_events._check_resolved_address(sock, address) + except ValueError as err: + fut.set_exception(err) + else: + self._sock_connect(fut, False, sock, address) return fut def _sock_connect(self, fut, registered, sock, address): - # TODO: Use getaddrinfo() to look up the address, to avoid the - # trap of hanging the entire event loop when the address - # requires doing a DNS lookup. (OTOH, the caller should - # already have done this, so it would be nice if we could - # easily tell whether the address needs looking up or not. I - # know how to do this for IPv4, but IPv6 addresses have many - # syntaxes.) fd = sock.fileno() if registered: self.remove_writer(fd) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1191,6 +1191,18 @@ {'clock_resolution': self.loop._clock_resolution, 'selector': self.loop._selector.__class__.__name__}) + def test_sock_connect_address(self): + address = ('www.python.org', 80) + for family in (socket.AF_INET, socket.AF_INET6): + for sock_type in (socket.SOCK_STREAM, socket.SOCK_DGRAM): + sock = socket.socket(family, sock_type) + with sock: + connect = self.loop.sock_connect(sock, address) + with self.assertRaises(ValueError) as cm: + self.loop.run_until_complete(connect) + self.assertIn('address must be resolved', + str(cm.exception)) + class SubprocessTestsMixin: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 13 10:47:30 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 13 Feb 2014 10:47:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_test=5Fasyncio/test=5F?= =?utf-8?q?events=2Epy=3A_skip_IPv6_if_IPv6_is_disabled_on_the_host?= Message-ID: <3fPtDf62MQzNLM@mail.python.org> http://hg.python.org/cpython/rev/3b0a1b3c0022 changeset: 89183:3b0a1b3c0022 user: Victor Stinner date: Thu Feb 13 10:46:05 2014 +0100 summary: Fix test_asyncio/test_events.py: skip IPv6 if IPv6 is disabled on the host files: Lib/test/test_asyncio/test_events.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1192,8 +1192,12 @@ 'selector': self.loop._selector.__class__.__name__}) def test_sock_connect_address(self): + families = [socket.AF_INET] + if support.IPV6_ENABLED: + families.append(socket.AF_INET6) + address = ('www.python.org', 80) - for family in (socket.AF_INET, socket.AF_INET6): + for family in families: for sock_type in (socket.SOCK_STREAM, socket.SOCK_DGRAM): sock = socket.socket(family, sock_type) with sock: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 13 10:54:53 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 13 Feb 2014 10:54:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320599=3A_Don=27t_?= =?utf-8?q?clear_environment_in_test=5Fcleanup=28=29_of_test=5Fbuiltin?= Message-ID: <3fPtP91jbFzSgC@mail.python.org> http://hg.python.org/cpython/rev/488ccbee6ee6 changeset: 89184:488ccbee6ee6 user: Victor Stinner date: Thu Feb 13 10:54:32 2014 +0100 summary: Issue #20599: Don't clear environment in test_cleanup() of test_builtin files: Lib/test/test_builtin.py | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1624,8 +1624,7 @@ # sys.stdout.encoding is the OEM code page and these code pages are # implemented in Python rc, out, err = assert_python_ok("-c", code, - PYTHONIOENCODING="ascii", - __cleanenv=True) + PYTHONIOENCODING="ascii") self.assertEqual(["before", "after"], out.decode().splitlines()) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 13 12:52:31 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 13 Feb 2014 12:52:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320526=2C_=2319466?= =?utf-8?q?=3A_Revert_changes_of_issue_=2319466_which_introduces_a?= Message-ID: <3fPx0v0znDz7LlB@mail.python.org> http://hg.python.org/cpython/rev/1166b3321012 changeset: 89185:1166b3321012 user: Victor Stinner date: Thu Feb 13 12:48:54 2014 +0100 summary: Issue #20526, #19466: Revert changes of issue #19466 which introduces a regression: don't clear anymore the state of Python threads early during the Python shutdown. files: Lib/test/test_threading.py | 49 -------------------------- Misc/NEWS | 4 ++ Python/pythonrun.c | 20 ++------- 3 files changed, 9 insertions(+), 64 deletions(-) diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -616,51 +616,6 @@ t.join() self.assertRaises(ValueError, bs.release) - def test_locals_at_exit(self): - # Issue #19466: thread locals must not be deleted before destructors - # are called - rc, out, err = assert_python_ok("-c", """if 1: - import threading - - class Atexit: - def __del__(self): - print("thread_dict.atexit = %r" % thread_dict.atexit) - - thread_dict = threading.local() - thread_dict.atexit = "atexit" - - atexit = Atexit() - """) - self.assertEqual(out.rstrip(), b"thread_dict.atexit = 'atexit'") - - def test_warnings_at_exit(self): - # Issue #19466: try to call most destructors at Python shutdown before - # destroying Python thread states - filename = __file__ - rc, out, err = assert_python_ok("-Wd", "-c", """if 1: - import time - import threading - - def open_sleep(): - # a warning will be emitted when the open file will be - # destroyed (without being explicitly closed) while the daemon - # thread is destroyed - fileobj = open(%a, 'rb') - start_event.set() - time.sleep(60.0) - - start_event = threading.Event() - - thread = threading.Thread(target=open_sleep) - thread.daemon = True - thread.start() - - # wait until the thread started - start_event.wait() - """ % filename) - self.assertRegex(err.rstrip(), - b"^sys:1: ResourceWarning: unclosed file ") - @cpython_only def test_frame_tstate_tracing(self): # Issue #14432: Crash when a generator is created in a C thread that is @@ -786,10 +741,6 @@ import sys import time import threading - import warnings - - # ignore "unclosed file ..." warnings - warnings.filterwarnings('ignore', '', ResourceWarning) thread_has_run = set() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #20526: Revert changes of issue #19466 which introduces a regression: + don't clear anymore the state of Python threads early during the Python + shutdown. + - Issue #20595: Make getargs.c C89 compliant. Library diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -582,13 +582,11 @@ _Py_Finalizing = tstate; initialized = 0; - /* Destroy the state of all threads except of the current thread: in - practice, only daemon threads should still be alive. Clear frames of - other threads to call objects destructor. Destructors will be called in - the current Python thread. Since _Py_Finalizing has been set, no other - Python threads can lock the GIL at this point (if they try, they will - exit immediately). */ - _PyThreadState_DeleteExcept(tstate); + /* Flush stdout+stderr */ + flush_std_files(); + + /* Disable signal handling */ + PyOS_FiniInterrupts(); /* Collect garbage. This may call finalizers; it's nice to call these * before all modules are destroyed. @@ -603,7 +601,6 @@ * XXX I haven't seen a real-life report of either of these. */ PyGC_Collect(); - #ifdef COUNT_ALLOCS /* With COUNT_ALLOCS, it helps to run GC multiple times: each collection might release some types from the type @@ -611,13 +608,6 @@ while (PyGC_Collect() > 0) /* nothing */; #endif - - /* Flush stdout+stderr */ - flush_std_files(); - - /* Disable signal handling */ - PyOS_FiniInterrupts(); - /* Destroy all modules */ PyImport_Cleanup(); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 14 01:22:28 2014 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 14 Feb 2014 01:22:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_set_line_and_column_number?= =?utf-8?q?s_for_keyword-only_arg_nodes_=28closes_=2320619=29?= Message-ID: <3fQFfD4pv2z7Lnk@mail.python.org> http://hg.python.org/cpython/rev/2dd4922c9371 changeset: 89186:2dd4922c9371 user: Benjamin Peterson date: Thu Feb 13 19:22:14 2014 -0500 summary: set line and column numbers for keyword-only arg nodes (closes #20619) files: Lib/test/test_ast.py | 4 ++-- Misc/NEWS | 3 +++ Python/ast.c | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -37,7 +37,7 @@ # FunctionDef with kwargs "def f(**kwargs): pass", # FunctionDef with all kind of args - "def f(a, b=1, c=None, d=[], e={}, *args, **kwargs): pass", + "def f(a, b=1, c=None, d=[], e={}, *args, f=42, **kwargs): pass", # ClassDef "class C:pass", # ClassDef, new style class @@ -973,7 +973,7 @@ ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None), [], [], None, []), [('Pass', (1, 14))], [], None)]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None)]), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [], [], ('arg', (1, 43), 'kwargs', None), [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Pass', (1, 52))], [], None)]), + ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [('arg', (1, 41), 'f', None)], [('Num', (1, 43), 42)], ('arg', (1, 49), 'kwargs', None), [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Pass', (1, 58))], [], None)]), ('Module', [('ClassDef', (1, 0), 'C', [], [], None, None, [('Pass', (1, 8))], [])]), ('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], None, None, [('Pass', (1, 17))], [])]), ('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None)]), diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #20619: Give the AST nodes of keyword-only arguments a column and line + number. + - Issue #20526: Revert changes of issue #19466 which introduces a regression: don't clear anymore the state of Python threads early during the Python shutdown. diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -1203,6 +1203,8 @@ arg = arg(argname, annotation, c->c_arena); if (!arg) goto error; + arg->lineno = LINENO(ch); + arg->col_offset = ch->n_col_offset; asdl_seq_SET(kwonlyargs, j++, arg); i += 2; /* the name and the comma */ break; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 14 06:04:35 2014 From: python-checkins at python.org (ezio.melotti) Date: Fri, 14 Feb 2014 06:04:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE5NjgwOiBhZGQg?= =?utf-8?q?back_documentation_for_print_and_exec_in_the_interactive_help?= =?utf-8?q?=2E?= Message-ID: <3fQMvl2HPxz7Ll3@mail.python.org> http://hg.python.org/cpython/rev/cc62d856fc5f changeset: 89187:cc62d856fc5f branch: 2.7 parent: 89167:712b4665955d user: Ezio Melotti date: Fri Feb 14 07:04:15 2014 +0200 summary: #19680: add back documentation for print and exec in the interactive help. files: Doc/tools/sphinxext/pyspecific.py | 4 ++-- Lib/pydoc_data/topics.py | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Doc/tools/sphinxext/pyspecific.py b/Doc/tools/sphinxext/pyspecific.py --- a/Doc/tools/sphinxext/pyspecific.py +++ b/Doc/tools/sphinxext/pyspecific.py @@ -184,11 +184,11 @@ 'bltin-null-object', 'bltin-type-objects', 'booleans', 'break', 'callable-types', 'calls', 'class', 'comparisons', 'compound', 'context-managers', 'continue', 'conversions', 'customization', 'debugger', - 'del', 'dict', 'dynamic-features', 'else', 'exceptions', 'execmodel', + 'del', 'dict', 'dynamic-features', 'else', 'exceptions', 'exec', 'execmodel', 'exprlists', 'floating', 'for', 'formatstrings', 'function', 'global', 'id-classes', 'identifiers', 'if', 'imaginary', 'import', 'in', 'integers', 'lambda', 'lists', 'naming', 'numbers', 'numeric-types', - 'objects', 'operator-summary', 'pass', 'power', 'raise', 'return', + 'objects', 'operator-summary', 'pass', 'power', 'print', 'raise', 'return', 'sequence-types', 'shifting', 'slicings', 'specialattrs', 'specialnames', 'string-methods', 'strings', 'subscriptions', 'truth', 'try', 'types', 'typesfunctions', 'typesmapping', 'typesmethods', 'typesmodules', diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,4 +1,4 @@ -# Autogenerated by Sphinx on Sat Oct 26 13:44:16 2013 +# Autogenerated by Sphinx on Fri Feb 14 06:59:30 2014 topics = {'assert': '\nThe ``assert`` statement\n************************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, ``assert expression``, is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, ``assert expression1, expression2``, is equivalent\nto\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that ``__debug__`` and ``AssertionError``\nrefer to the built-in variables with those names. In the current\nimplementation, the built-in variable ``__debug__`` is ``True`` under\nnormal circumstances, ``False`` when optimization is requested\n(command line option -O). The current code generator emits no code\nfor an assert statement when optimization is requested at compile\ntime. Note that it is unnecessary to include the source code for the\nexpression that failed in the error message; it will be displayed as\npart of the stack trace.\n\nAssignments to ``__debug__`` are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': '\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list is recursively defined as\nfollows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The object\n must be an iterable with the same number of items as there are\n targets in the target list, and the items are assigned, from left to\n right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a ``global`` statement in the\n current code block: the name is bound to the object in the current\n local namespace.\n\n * Otherwise: the name is bound to the object in the current global\n namespace.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in square\n brackets: The object must be an iterable with the same number of\n items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, ``TypeError`` is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily ``AttributeError``).\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n ``a.x`` can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target ``a.x`` is\n always set as an instance attribute, creating it if necessary.\n Thus, the two occurrences of ``a.x`` do not necessarily refer to the\n same attribute: if the RHS expression refers to a class attribute,\n the LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with ``property()``.\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield a plain integer. If it is negative, the\n sequence\'s length is added to it. The resulting value must be a\n nonnegative integer less than the sequence\'s length, and the\n sequence is asked to assign the assigned object to its item with\n that index. If the index is out of range, ``IndexError`` is raised\n (assignment to a subscripted sequence cannot add new items to a\n list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n* If the target is a slicing: The primary expression in the reference\n is evaluated. It should yield a mutable sequence object (such as a\n list). The assigned object should be a sequence object of the same\n type. Next, the lower and upper bound expressions are evaluated,\n insofar they are present; defaults are zero and the sequence\'s\n length. The bounds should evaluate to (small) integers. If either\n bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample ``a, b = b, a`` swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints ``[0, 2]``:\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print x\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like ``x += 1`` can be rewritten as\n``x = x + 1`` to achieve a similar, but not exactly equal effect. In\nthe augmented version, ``x`` is only evaluated once. Also, when\npossible, the actual operation is performed *in-place*, meaning that\nrather than creating a new object and assigning that to the target,\nthe old object is modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': '\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a ``NameError`` exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier\n``__spam`` occurring in a class named ``Ham`` will be transformed to\n``_Ham__spam``. This transformation is independent of the syntactical\ncontext in which the identifier is used. If the transformed name is\nextremely long (longer than 255 characters), implementation defined\ntruncation may happen. If the class name consists only of underscores,\nno transformation is done.\n', @@ -29,11 +29,12 @@ 'dynamic-features': '\nInteraction with dynamic features\n*********************************\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- ``import *`` --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a ``SyntaxError``.\n\nIf ``exec`` is used in a function and the function contains or is a\nnested block with free variables, the compiler will raise a\n``SyntaxError`` unless the exec explicitly specifies the local\nnamespace for the ``exec``. (In other words, ``exec obj`` would be\nillegal, but ``exec obj in ns`` would be legal.)\n\nThe ``eval()``, ``execfile()``, and ``input()`` functions and the\n``exec`` statement do not have access to the full environment for\nresolving names. Names may be resolved in the local and global\nnamespaces of the caller. Free variables are not resolved in the\nnearest enclosing namespace, but in the global namespace. [1] The\n``exec`` statement and the ``eval()`` and ``execfile()`` functions\nhave optional arguments to override the global and local namespace.\nIf only one namespace is specified, it is used for both.\n', 'else': '\nThe ``if`` statement\n********************\n\nThe ``if`` statement is used for conditional execution:\n\n if_stmt ::= "if" expression ":" suite\n ( "elif" expression ":" suite )*\n ["else" ":" suite]\n\nIt selects exactly one of the suites by evaluating the expressions one\nby one until one is found to be true (see section *Boolean operations*\nfor the definition of true and false); then that suite is executed\n(and no other part of the ``if`` statement is executed or evaluated).\nIf all expressions are false, the suite of the ``else`` clause, if\npresent, is executed.\n', 'exceptions': '\nExceptions\n**********\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the ``raise`` statement. Exception\nhandlers are specified with the ``try`` ... ``except`` statement. The\n``finally`` clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n``SystemExit``.\n\nExceptions are identified by class instances. The ``except`` clause\nis selected depending on the class of the instance: it must reference\nthe class of the instance or a base class thereof. The instance can\nbe received by the handler and can carry additional information about\nthe exceptional condition.\n\nExceptions can also be identified by strings, in which case the\n``except`` clause is selected by object identity. An arbitrary value\ncan be raised along with the identifying string which can be passed to\nthe handler.\n\nNote: Messages to exceptions are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the ``try`` statement in section *The try\nstatement* and ``raise`` statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by these\n operations is not available at the time the module is compiled.\n', + 'exec': '\nThe ``exec`` statement\n**********************\n\n exec_stmt ::= "exec" or_expr ["in" expression ["," expression]]\n\nThis statement supports dynamic execution of Python code. The first\nexpression should evaluate to either a Unicode string, a *Latin-1*\nencoded string, an open file object, a code object, or a tuple. If it\nis a string, the string is parsed as a suite of Python statements\nwhich is then executed (unless a syntax error occurs). [1] If it is an\nopen file, the file is parsed until EOF and executed. If it is a code\nobject, it is simply executed. For the interpretation of a tuple, see\nbelow. In all cases, the code that\'s executed is expected to be valid\nas file input (see section *File input*). Be aware that the\n``return`` and ``yield`` statements may not be used outside of\nfunction definitions even within the context of code passed to the\n``exec`` statement.\n\nIn all cases, if the optional parts are omitted, the code is executed\nin the current scope. If only the first expression after ``in`` is\nspecified, it should be a dictionary, which will be used for both the\nglobal and the local variables. If two expressions are given, they\nare used for the global and local variables, respectively. If\nprovided, *locals* can be any mapping object. Remember that at module\nlevel, globals and locals are the same dictionary. If two separate\nobjects are given as *globals* and *locals*, the code will be executed\nas if it were embedded in a class definition.\n\nThe first expression may also be a tuple of length 2 or 3. In this\ncase, the optional parts must be omitted. The form ``exec(expr,\nglobals)`` is equivalent to ``exec expr in globals``, while the form\n``exec(expr, globals, locals)`` is equivalent to ``exec expr in\nglobals, locals``. The tuple form of ``exec`` provides compatibility\nwith Python 3, where ``exec`` is a function rather than a statement.\n\nChanged in version 2.4: Formerly, *locals* was required to be a\ndictionary.\n\nAs a side effect, an implementation may insert additional keys into\nthe dictionaries given besides those corresponding to variable names\nset by the executed code. For example, the current implementation may\nadd a reference to the dictionary of the built-in module\n``__builtin__`` under the key ``__builtins__`` (!).\n\n**Programmer\'s hints:** dynamic evaluation of expressions is supported\nby the built-in function ``eval()``. The built-in functions\n``globals()`` and ``locals()`` return the current global and local\ndictionary, respectively, which may be useful to pass around for use\nby ``exec``.\n\n-[ Footnotes ]-\n\n[1] Note that the parser only accepts the Unix-style end of line\n convention. If you are reading the code from a file, make sure to\n use *universal newlines* mode to convert Windows or Mac-style\n newlines.\n', 'execmodel': '\nExecution model\n***************\n\n\nNaming and binding\n==================\n\n*Names* refer to objects. Names are introduced by name binding\noperations. Each occurrence of a name in the program text refers to\nthe *binding* of that name established in the innermost function block\ncontaining the use.\n\nA *block* is a piece of Python program text that is executed as a\nunit. The following are blocks: a module, a function body, and a class\ndefinition. Each command typed interactively is a block. A script\nfile (a file given as standard input to the interpreter or specified\non the interpreter command line the first argument) is a code block.\nA script command (a command specified on the interpreter command line\nwith the \'**-c**\' option) is a code block. The file read by the\nbuilt-in function ``execfile()`` is a code block. The string argument\npassed to the built-in function ``eval()`` and to the ``exec``\nstatement is a code block. The expression read and evaluated by the\nbuilt-in function ``input()`` is a code block.\n\nA code block is executed in an *execution frame*. A frame contains\nsome administrative information (used for debugging) and determines\nwhere and how execution continues after the code block\'s execution has\ncompleted.\n\nA *scope* defines the visibility of a name within a block. If a local\nvariable is defined in a block, its scope includes that block. If the\ndefinition occurs in a function block, the scope extends to any blocks\ncontained within the defining one, unless a contained block introduces\na different binding for the name. The scope of names defined in a\nclass block is limited to the class block; it does not extend to the\ncode blocks of methods -- this includes generator expressions since\nthey are implemented using a function scope. This means that the\nfollowing will fail:\n\n class A:\n a = 42\n b = list(a + i for i in range(10))\n\nWhen a name is used in a code block, it is resolved using the nearest\nenclosing scope. The set of all such scopes visible to a code block\nis called the block\'s *environment*.\n\nIf a name is bound in a block, it is a local variable of that block.\nIf a name is bound at the module level, it is a global variable. (The\nvariables of the module code block are local and global.) If a\nvariable is used in a code block but not defined there, it is a *free\nvariable*.\n\nWhen a name is not found at all, a ``NameError`` exception is raised.\nIf the name refers to a local variable that has not been bound, a\n``UnboundLocalError`` exception is raised. ``UnboundLocalError`` is a\nsubclass of ``NameError``.\n\nThe following constructs bind names: formal parameters to functions,\n``import`` statements, class and function definitions (these bind the\nclass or function name in the defining block), and targets that are\nidentifiers if occurring in an assignment, ``for`` loop header, in the\nsecond position of an ``except`` clause header or after ``as`` in a\n``with`` statement. The ``import`` statement of the form ``from ...\nimport *`` binds all names defined in the imported module, except\nthose beginning with an underscore. This form may only be used at the\nmodule level.\n\nA target occurring in a ``del`` statement is also considered bound for\nthis purpose (though the actual semantics are to unbind the name). It\nis illegal to unbind a name that is referenced by an enclosing scope;\nthe compiler will report a ``SyntaxError``.\n\nEach assignment or import statement occurs within a block defined by a\nclass or function definition or at the module level (the top-level\ncode block).\n\nIf a name binding operation occurs anywhere within a code block, all\nuses of the name within the block are treated as references to the\ncurrent block. This can lead to errors when a name is used within a\nblock before it is bound. This rule is subtle. Python lacks\ndeclarations and allows name binding operations to occur anywhere\nwithin a code block. The local variables of a code block can be\ndetermined by scanning the entire text of the block for name binding\noperations.\n\nIf the global statement occurs within a block, all uses of the name\nspecified in the statement refer to the binding of that name in the\ntop-level namespace. Names are resolved in the top-level namespace by\nsearching the global namespace, i.e. the namespace of the module\ncontaining the code block, and the builtins namespace, the namespace\nof the module ``__builtin__``. The global namespace is searched\nfirst. If the name is not found there, the builtins namespace is\nsearched. The global statement must precede all uses of the name.\n\nThe builtins namespace associated with the execution of a code block\nis actually found by looking up the name ``__builtins__`` in its\nglobal namespace; this should be a dictionary or a module (in the\nlatter case the module\'s dictionary is used). By default, when in the\n``__main__`` module, ``__builtins__`` is the built-in module\n``__builtin__`` (note: no \'s\'); when in any other module,\n``__builtins__`` is an alias for the dictionary of the ``__builtin__``\nmodule itself. ``__builtins__`` can be set to a user-created\ndictionary to create a weak form of restricted execution.\n\n**CPython implementation detail:** Users should not touch\n``__builtins__``; it is strictly an implementation detail. Users\nwanting to override values in the builtins namespace should ``import``\nthe ``__builtin__`` (no \'s\') module and modify its attributes\nappropriately.\n\nThe namespace for a module is automatically created the first time a\nmodule is imported. The main module for a script is always called\n``__main__``.\n\nThe ``global`` statement has the same scope as a name binding\noperation in the same block. If the nearest enclosing scope for a\nfree variable contains a global statement, the free variable is\ntreated as a global.\n\nA class definition is an executable statement that may use and define\nnames. These references follow the normal rules for name resolution.\nThe namespace of the class definition becomes the attribute dictionary\nof the class. Names defined at the class scope are not visible in\nmethods.\n\n\nInteraction with dynamic features\n---------------------------------\n\nThere are several cases where Python statements are illegal when used\nin conjunction with nested scopes that contain free variables.\n\nIf a variable is referenced in an enclosing scope, it is illegal to\ndelete the name. An error will be reported at compile time.\n\nIf the wild card form of import --- ``import *`` --- is used in a\nfunction and the function contains or is a nested block with free\nvariables, the compiler will raise a ``SyntaxError``.\n\nIf ``exec`` is used in a function and the function contains or is a\nnested block with free variables, the compiler will raise a\n``SyntaxError`` unless the exec explicitly specifies the local\nnamespace for the ``exec``. (In other words, ``exec obj`` would be\nillegal, but ``exec obj in ns`` would be legal.)\n\nThe ``eval()``, ``execfile()``, and ``input()`` functions and the\n``exec`` statement do not have access to the full environment for\nresolving names. Names may be resolved in the local and global\nnamespaces of the caller. Free variables are not resolved in the\nnearest enclosing namespace, but in the global namespace. [1] The\n``exec`` statement and the ``eval()`` and ``execfile()`` functions\nhave optional arguments to override the global and local namespace.\nIf only one namespace is specified, it is used for both.\n\n\nExceptions\n==========\n\nExceptions are a means of breaking out of the normal flow of control\nof a code block in order to handle errors or other exceptional\nconditions. An exception is *raised* at the point where the error is\ndetected; it may be *handled* by the surrounding code block or by any\ncode block that directly or indirectly invoked the code block where\nthe error occurred.\n\nThe Python interpreter raises an exception when it detects a run-time\nerror (such as division by zero). A Python program can also\nexplicitly raise an exception with the ``raise`` statement. Exception\nhandlers are specified with the ``try`` ... ``except`` statement. The\n``finally`` clause of such a statement can be used to specify cleanup\ncode which does not handle the exception, but is executed whether an\nexception occurred or not in the preceding code.\n\nPython uses the "termination" model of error handling: an exception\nhandler can find out what happened and continue execution at an outer\nlevel, but it cannot repair the cause of the error and retry the\nfailing operation (except by re-entering the offending piece of code\nfrom the top).\n\nWhen an exception is not handled at all, the interpreter terminates\nexecution of the program, or returns to its interactive main loop. In\neither case, it prints a stack backtrace, except when the exception is\n``SystemExit``.\n\nExceptions are identified by class instances. The ``except`` clause\nis selected depending on the class of the instance: it must reference\nthe class of the instance or a base class thereof. The instance can\nbe received by the handler and can carry additional information about\nthe exceptional condition.\n\nExceptions can also be identified by strings, in which case the\n``except`` clause is selected by object identity. An arbitrary value\ncan be raised along with the identifying string which can be passed to\nthe handler.\n\nNote: Messages to exceptions are not part of the Python API. Their\n contents may change from one version of Python to the next without\n warning and should not be relied on by code which will run under\n multiple versions of the interpreter.\n\nSee also the description of the ``try`` statement in section *The try\nstatement* and ``raise`` statement in section *The raise statement*.\n\n-[ Footnotes ]-\n\n[1] This limitation occurs because the code that is executed by these\n operations is not available at the time the module is compiled.\n', 'exprlists': '\nExpression lists\n****************\n\n expression_list ::= expression ( "," expression )* [","]\n\nAn expression list containing at least one comma yields a tuple. The\nlength of the tuple is the number of expressions in the list. The\nexpressions are evaluated from left to right.\n\nThe trailing comma is required only to create a single tuple (a.k.a. a\n*singleton*); it is optional in all other cases. A single expression\nwithout a trailing comma doesn\'t create a tuple, but rather yields the\nvalue of that expression. (To create an empty tuple, use an empty pair\nof parentheses: ``()``.)\n', 'floating': '\nFloating point literals\n***********************\n\nFloating point literals are described by the following lexical\ndefinitions:\n\n floatnumber ::= pointfloat | exponentfloat\n pointfloat ::= [intpart] fraction | intpart "."\n exponentfloat ::= (intpart | pointfloat) exponent\n intpart ::= digit+\n fraction ::= "." digit+\n exponent ::= ("e" | "E") ["+" | "-"] digit+\n\nNote that the integer and exponent parts of floating point numbers can\nlook like octal integers, but are interpreted using radix 10. For\nexample, ``077e010`` is legal, and denotes the same number as\n``77e10``. The allowed range of floating point literals is\nimplementation-dependent. Some examples of floating point literals:\n\n 3.14 10. .001 1e100 3.14e-10 0e0\n\nNote that numeric literals do not include a sign; a phrase like ``-1``\nis actually an expression composed of the unary operator ``-`` and the\nliteral ``1``.\n', 'for': '\nThe ``for`` statement\n*********************\n\nThe ``for`` statement is used to iterate over the elements of a\nsequence (such as a string, tuple or list) or other iterable object:\n\n for_stmt ::= "for" target_list "in" expression_list ":" suite\n ["else" ":" suite]\n\nThe expression list is evaluated once; it should yield an iterable\nobject. An iterator is created for the result of the\n``expression_list``. The suite is then executed once for each item\nprovided by the iterator, in the order of ascending indices. Each\nitem in turn is assigned to the target list using the standard rules\nfor assignments, and then the suite is executed. When the items are\nexhausted (which is immediately when the sequence is empty), the suite\nin the ``else`` clause, if present, is executed, and the loop\nterminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ncontinues with the next item, or with the ``else`` clause if there was\nno next item.\n\nThe suite may assign to the variable(s) in the target list; this does\nnot affect the next item assigned to it.\n\nThe target list is not deleted when the loop is finished, but if the\nsequence is empty, it will not have been assigned to at all by the\nloop. Hint: the built-in function ``range()`` returns a sequence of\nintegers suitable to emulate the effect of Pascal\'s ``for i := a to b\ndo``; e.g., ``range(3)`` returns the list ``[0, 1, 2]``.\n\nNote: There is a subtlety when the sequence is being modified by the loop\n (this can only occur for mutable sequences, i.e. lists). An internal\n counter is used to keep track of which item is used next, and this\n is incremented on each iteration. When this counter has reached the\n length of the sequence the loop terminates. This means that if the\n suite deletes the current (or a previous) item from the sequence,\n the next item will be skipped (since it gets the index of the\n current item which has already been treated). Likewise, if the\n suite inserts an item in the sequence before the current item, the\n current item will be treated again the next time through the loop.\n This can lead to nasty bugs that can be avoided by making a\n temporary copy using a slice of the whole sequence, e.g.,\n\n for x in a[:]:\n if x < 0: a.remove(x)\n', - 'formatstrings': '\nFormat String Syntax\n********************\n\nThe ``str.format()`` method and the ``Formatter`` class share the same\nsyntax for format strings (although in the case of ``Formatter``,\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n``{}``. Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n``{{`` and ``}}``.\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= +\n conversion ::= "r" | "s"\n format_spec ::= \n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point ``\'!\'``, and a *format_spec*, which\nis preceded by a colon ``\':\'``. These specify a non-default format\nfor the replacement value.\n\nSee also the *Format Specification Mini-Language* section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings ``\'10\'`` or\n``\':-]\'``) within a format string. The *arg_name* can be followed by\nany number of index or attribute expressions. An expression of the\nform ``\'.name\'`` selects the named attribute using ``getattr()``,\nwhile an expression of the form ``\'[index]\'`` does an index lookup\nusing ``__getitem__()``.\n\nChanged in version 2.7: The positional argument specifiers can be\nomitted, so ``\'{} {}\'`` is equivalent to ``\'{0} {1}\'``.\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the\n``__format__()`` method of the value itself. However, in some cases\nit is desirable to force a type to be formatted as a string,\noverriding its own definition of formatting. By converting the value\nto a string before calling ``__format__()``, the normal formatting\nlogic is bypassed.\n\nTwo conversion flags are currently supported: ``\'!s\'`` which calls\n``str()`` on the value, and ``\'!r\'`` which calls ``repr()``.\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields can contain only a field\nname; conversion flags and format specifications are not allowed. The\nreplacement fields within the format_spec are substituted before the\n*format_spec* string is interpreted. This allows the formatting of a\nvalue to be dynamically specified.\n\nSee the *Format examples* section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see *Format String Syntax*). They can also be passed directly to the\nbuilt-in ``format()`` function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string (``""``) produces\nthe same result as if you had called ``str()`` on the value. A non-\nempty format string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= \n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nIf a valid *align* value is specified, it can be preceeded by a *fill*\ncharacter that can be any character and defaults to a space if\nomitted. Note that it is not possible to use ``{`` and ``}`` as *fill*\nchar while using the ``str.format()`` method; this limitation however\ndoesn\'t affect the ``format()`` function.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | ``\'<\'`` | Forces the field to be left-aligned within the available |\n | | space (this is the default for most objects). |\n +-----------+------------------------------------------------------------+\n | ``\'>\'`` | Forces the field to be right-aligned within the available |\n | | space (this is the default for numbers). |\n +-----------+------------------------------------------------------------+\n | ``\'=\'`` | Forces the padding to be placed after the sign (if any) |\n | | but before the digits. This is used for printing fields |\n | | in the form \'+000000120\'. This alignment option is only |\n | | valid for numeric types. |\n +-----------+------------------------------------------------------------+\n | ``\'^\'`` | Forces the field to be centered within the available |\n | | space. |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | ``\'+\'`` | indicates that a sign should be used for both positive as |\n | | well as negative numbers. |\n +-----------+------------------------------------------------------------+\n | ``\'-\'`` | indicates that a sign should be used only for negative |\n | | numbers (this is the default behavior). |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n | | numbers, and a minus sign on negative numbers. |\n +-----------+------------------------------------------------------------+\n\nThe ``\'#\'`` option is only valid for integers, and only for binary,\noctal, or hexadecimal output. If present, it specifies that the\noutput will be prefixed by ``\'0b\'``, ``\'0o\'``, or ``\'0x\'``,\nrespectively.\n\nThe ``\',\'`` option signals the use of a comma for a thousands\nseparator. For a locale aware separator, use the ``\'n\'`` integer\npresentation type instead.\n\nChanged in version 2.7: Added the ``\',\'`` option (see also **PEP\n378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nPreceding the *width* field by a zero (``\'0\'``) character enables\nsign-aware zero-padding for numeric types. This is equivalent to a\n*fill* character of ``\'0\'`` with an *alignment* type of ``\'=\'``.\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with ``\'f\'`` and ``\'F\'``, or before and after the decimal\npoint for a floating point value formatted with ``\'g\'`` or ``\'G\'``.\nFor non-number types the field indicates the maximum field size - in\nother words, how many characters will be used from the field content.\nThe *precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'s\'`` | String format. This is the default type for strings and |\n | | may be omitted. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'s\'``. |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'b\'`` | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | ``\'c\'`` | Character. Converts the integer to the corresponding |\n | | unicode character before printing. |\n +-----------+------------------------------------------------------------+\n | ``\'d\'`` | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | ``\'o\'`` | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | ``\'x\'`` | Hex format. Outputs the number in base 16, using lower- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | ``\'X\'`` | Hex format. Outputs the number in base 16, using upper- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | ``\'n\'`` | Number. This is the same as ``\'d\'``, except that it uses |\n | | the current locale setting to insert the appropriate |\n | | number separator characters. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'d\'``. |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except\n``\'n\'`` and None). When doing so, ``float()`` is used to convert the\ninteger to a floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'e\'`` | Exponent notation. Prints the number in scientific |\n | | notation using the letter \'e\' to indicate the exponent. |\n | | The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'E\'`` | Exponent notation. Same as ``\'e\'`` except it uses an upper |\n | | case \'E\' as the separator character. |\n +-----------+------------------------------------------------------------+\n | ``\'f\'`` | Fixed point. Displays the number as a fixed-point number. |\n | | The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'F\'`` | Fixed point. Same as ``\'f\'``. |\n +-----------+------------------------------------------------------------+\n | ``\'g\'`` | General format. For a given precision ``p >= 1``, this |\n | | rounds the number to ``p`` significant digits and then |\n | | formats the result in either fixed-point format or in |\n | | scientific notation, depending on its magnitude. The |\n | | precise rules are as follows: suppose that the result |\n | | formatted with presentation type ``\'e\'`` and precision |\n | | ``p-1`` would have exponent ``exp``. Then if ``-4 <= exp |\n | | < p``, the number is formatted with presentation type |\n | | ``\'f\'`` and precision ``p-1-exp``. Otherwise, the number |\n | | is formatted with presentation type ``\'e\'`` and precision |\n | | ``p-1``. In both cases insignificant trailing zeros are |\n | | removed from the significand, and the decimal point is |\n | | also removed if there are no remaining digits following |\n | | it. Positive and negative infinity, positive and negative |\n | | zero, and nans, are formatted as ``inf``, ``-inf``, ``0``, |\n | | ``-0`` and ``nan`` respectively, regardless of the |\n | | precision. A precision of ``0`` is treated as equivalent |\n | | to a precision of ``1``. The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'G\'`` | General format. Same as ``\'g\'`` except switches to ``\'E\'`` |\n | | if the number gets too large. The representations of |\n | | infinity and NaN are uppercased, too. |\n +-----------+------------------------------------------------------------+\n | ``\'n\'`` | Number. This is the same as ``\'g\'``, except that it uses |\n | | the current locale setting to insert the appropriate |\n | | number separator characters. |\n +-----------+------------------------------------------------------------+\n | ``\'%\'`` | Percentage. Multiplies the number by 100 and displays in |\n | | fixed (``\'f\'``) format, followed by a percent sign. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'g\'``. |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the new format syntax and comparison\nwith the old ``%``-formatting.\n\nIn most of the cases the syntax is similar to the old\n``%``-formatting, with the addition of the ``{}`` and with ``:`` used\ninstead of ``%``. For example, ``\'%03.2f\'`` can be translated to\n``\'{:03.2f}\'``.\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 2.7+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point(object):\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing ``%s`` and ``%r``:\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing ``%x`` and ``%o`` and converting the value to different\nbases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19.5\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 88.64%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12):\n ... for base in \'dXob\':\n ... print \'{0:{width}{base}}\'.format(num, base=base, width=width),\n ... print\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n', + 'formatstrings': '\nFormat String Syntax\n********************\n\nThe ``str.format()`` method and the ``Formatter`` class share the same\nsyntax for format strings (although in the case of ``Formatter``,\nsubclasses can define their own format string syntax).\n\nFormat strings contain "replacement fields" surrounded by curly braces\n``{}``. Anything that is not contained in braces is considered literal\ntext, which is copied unchanged to the output. If you need to include\na brace character in the literal text, it can be escaped by doubling:\n``{{`` and ``}}``.\n\nThe grammar for a replacement field is as follows:\n\n replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}"\n field_name ::= arg_name ("." attribute_name | "[" element_index "]")*\n arg_name ::= [identifier | integer]\n attribute_name ::= identifier\n element_index ::= integer | index_string\n index_string ::= +\n conversion ::= "r" | "s"\n format_spec ::= \n\nIn less formal terms, the replacement field can start with a\n*field_name* that specifies the object whose value is to be formatted\nand inserted into the output instead of the replacement field. The\n*field_name* is optionally followed by a *conversion* field, which is\npreceded by an exclamation point ``\'!\'``, and a *format_spec*, which\nis preceded by a colon ``\':\'``. These specify a non-default format\nfor the replacement value.\n\nSee also the *Format Specification Mini-Language* section.\n\nThe *field_name* itself begins with an *arg_name* that is either a\nnumber or a keyword. If it\'s a number, it refers to a positional\nargument, and if it\'s a keyword, it refers to a named keyword\nargument. If the numerical arg_names in a format string are 0, 1, 2,\n... in sequence, they can all be omitted (not just some) and the\nnumbers 0, 1, 2, ... will be automatically inserted in that order.\nBecause *arg_name* is not quote-delimited, it is not possible to\nspecify arbitrary dictionary keys (e.g., the strings ``\'10\'`` or\n``\':-]\'``) within a format string. The *arg_name* can be followed by\nany number of index or attribute expressions. An expression of the\nform ``\'.name\'`` selects the named attribute using ``getattr()``,\nwhile an expression of the form ``\'[index]\'`` does an index lookup\nusing ``__getitem__()``.\n\nChanged in version 2.7: The positional argument specifiers can be\nomitted, so ``\'{} {}\'`` is equivalent to ``\'{0} {1}\'``.\n\nSome simple format string examples:\n\n "First, thou shalt count to {0}" # References first positional argument\n "Bring me a {}" # Implicitly references the first positional argument\n "From {} to {}" # Same as "From {0} to {1}"\n "My quest is {name}" # References keyword argument \'name\'\n "Weight in tons {0.weight}" # \'weight\' attribute of first positional arg\n "Units destroyed: {players[0]}" # First element of keyword argument \'players\'.\n\nThe *conversion* field causes a type coercion before formatting.\nNormally, the job of formatting a value is done by the\n``__format__()`` method of the value itself. However, in some cases\nit is desirable to force a type to be formatted as a string,\noverriding its own definition of formatting. By converting the value\nto a string before calling ``__format__()``, the normal formatting\nlogic is bypassed.\n\nTwo conversion flags are currently supported: ``\'!s\'`` which calls\n``str()`` on the value, and ``\'!r\'`` which calls ``repr()``.\n\nSome examples:\n\n "Harold\'s a clever {0!s}" # Calls str() on the argument first\n "Bring out the holy {name!r}" # Calls repr() on the argument first\n\nThe *format_spec* field contains a specification of how the value\nshould be presented, including such details as field width, alignment,\npadding, decimal precision and so on. Each value type can define its\nown "formatting mini-language" or interpretation of the *format_spec*.\n\nMost built-in types support a common formatting mini-language, which\nis described in the next section.\n\nA *format_spec* field can also include nested replacement fields\nwithin it. These nested replacement fields can contain only a field\nname; conversion flags and format specifications are not allowed. The\nreplacement fields within the format_spec are substituted before the\n*format_spec* string is interpreted. This allows the formatting of a\nvalue to be dynamically specified.\n\nSee the *Format examples* section for some examples.\n\n\nFormat Specification Mini-Language\n==================================\n\n"Format specifications" are used within replacement fields contained\nwithin a format string to define how individual values are presented\n(see *Format String Syntax*). They can also be passed directly to the\nbuilt-in ``format()`` function. Each formattable type may define how\nthe format specification is to be interpreted.\n\nMost built-in types implement the following options for format\nspecifications, although some of the formatting options are only\nsupported by the numeric types.\n\nA general convention is that an empty format string (``""``) produces\nthe same result as if you had called ``str()`` on the value. A non-\nempty format string typically modifies the result.\n\nThe general form of a *standard format specifier* is:\n\n format_spec ::= [[fill]align][sign][#][0][width][,][.precision][type]\n fill ::= \n align ::= "<" | ">" | "=" | "^"\n sign ::= "+" | "-" | " "\n width ::= integer\n precision ::= integer\n type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n\nIf a valid *align* value is specified, it can be preceded by a *fill*\ncharacter that can be any character and defaults to a space if\nomitted. Note that it is not possible to use ``{`` and ``}`` as *fill*\nchar while using the ``str.format()`` method; this limitation however\ndoesn\'t affect the ``format()`` function.\n\nThe meaning of the various alignment options is as follows:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | ``\'<\'`` | Forces the field to be left-aligned within the available |\n | | space (this is the default for most objects). |\n +-----------+------------------------------------------------------------+\n | ``\'>\'`` | Forces the field to be right-aligned within the available |\n | | space (this is the default for numbers). |\n +-----------+------------------------------------------------------------+\n | ``\'=\'`` | Forces the padding to be placed after the sign (if any) |\n | | but before the digits. This is used for printing fields |\n | | in the form \'+000000120\'. This alignment option is only |\n | | valid for numeric types. |\n +-----------+------------------------------------------------------------+\n | ``\'^\'`` | Forces the field to be centered within the available |\n | | space. |\n +-----------+------------------------------------------------------------+\n\nNote that unless a minimum field width is defined, the field width\nwill always be the same size as the data to fill it, so that the\nalignment option has no meaning in this case.\n\nThe *sign* option is only valid for number types, and can be one of\nthe following:\n\n +-----------+------------------------------------------------------------+\n | Option | Meaning |\n +===========+============================================================+\n | ``\'+\'`` | indicates that a sign should be used for both positive as |\n | | well as negative numbers. |\n +-----------+------------------------------------------------------------+\n | ``\'-\'`` | indicates that a sign should be used only for negative |\n | | numbers (this is the default behavior). |\n +-----------+------------------------------------------------------------+\n | space | indicates that a leading space should be used on positive |\n | | numbers, and a minus sign on negative numbers. |\n +-----------+------------------------------------------------------------+\n\nThe ``\'#\'`` option is only valid for integers, and only for binary,\noctal, or hexadecimal output. If present, it specifies that the\noutput will be prefixed by ``\'0b\'``, ``\'0o\'``, or ``\'0x\'``,\nrespectively.\n\nThe ``\',\'`` option signals the use of a comma for a thousands\nseparator. For a locale aware separator, use the ``\'n\'`` integer\npresentation type instead.\n\nChanged in version 2.7: Added the ``\',\'`` option (see also **PEP\n378**).\n\n*width* is a decimal integer defining the minimum field width. If not\nspecified, then the field width will be determined by the content.\n\nPreceding the *width* field by a zero (``\'0\'``) character enables\nsign-aware zero-padding for numeric types. This is equivalent to a\n*fill* character of ``\'0\'`` with an *alignment* type of ``\'=\'``.\n\nThe *precision* is a decimal number indicating how many digits should\nbe displayed after the decimal point for a floating point value\nformatted with ``\'f\'`` and ``\'F\'``, or before and after the decimal\npoint for a floating point value formatted with ``\'g\'`` or ``\'G\'``.\nFor non-number types the field indicates the maximum field size - in\nother words, how many characters will be used from the field content.\nThe *precision* is not allowed for integer values.\n\nFinally, the *type* determines how the data should be presented.\n\nThe available string presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'s\'`` | String format. This is the default type for strings and |\n | | may be omitted. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'s\'``. |\n +-----------+------------------------------------------------------------+\n\nThe available integer presentation types are:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'b\'`` | Binary format. Outputs the number in base 2. |\n +-----------+------------------------------------------------------------+\n | ``\'c\'`` | Character. Converts the integer to the corresponding |\n | | unicode character before printing. |\n +-----------+------------------------------------------------------------+\n | ``\'d\'`` | Decimal Integer. Outputs the number in base 10. |\n +-----------+------------------------------------------------------------+\n | ``\'o\'`` | Octal format. Outputs the number in base 8. |\n +-----------+------------------------------------------------------------+\n | ``\'x\'`` | Hex format. Outputs the number in base 16, using lower- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | ``\'X\'`` | Hex format. Outputs the number in base 16, using upper- |\n | | case letters for the digits above 9. |\n +-----------+------------------------------------------------------------+\n | ``\'n\'`` | Number. This is the same as ``\'d\'``, except that it uses |\n | | the current locale setting to insert the appropriate |\n | | number separator characters. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'d\'``. |\n +-----------+------------------------------------------------------------+\n\nIn addition to the above presentation types, integers can be formatted\nwith the floating point presentation types listed below (except\n``\'n\'`` and None). When doing so, ``float()`` is used to convert the\ninteger to a floating point number before formatting.\n\nThe available presentation types for floating point and decimal values\nare:\n\n +-----------+------------------------------------------------------------+\n | Type | Meaning |\n +===========+============================================================+\n | ``\'e\'`` | Exponent notation. Prints the number in scientific |\n | | notation using the letter \'e\' to indicate the exponent. |\n | | The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'E\'`` | Exponent notation. Same as ``\'e\'`` except it uses an upper |\n | | case \'E\' as the separator character. |\n +-----------+------------------------------------------------------------+\n | ``\'f\'`` | Fixed point. Displays the number as a fixed-point number. |\n | | The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'F\'`` | Fixed point. Same as ``\'f\'``. |\n +-----------+------------------------------------------------------------+\n | ``\'g\'`` | General format. For a given precision ``p >= 1``, this |\n | | rounds the number to ``p`` significant digits and then |\n | | formats the result in either fixed-point format or in |\n | | scientific notation, depending on its magnitude. The |\n | | precise rules are as follows: suppose that the result |\n | | formatted with presentation type ``\'e\'`` and precision |\n | | ``p-1`` would have exponent ``exp``. Then if ``-4 <= exp |\n | | < p``, the number is formatted with presentation type |\n | | ``\'f\'`` and precision ``p-1-exp``. Otherwise, the number |\n | | is formatted with presentation type ``\'e\'`` and precision |\n | | ``p-1``. In both cases insignificant trailing zeros are |\n | | removed from the significand, and the decimal point is |\n | | also removed if there are no remaining digits following |\n | | it. Positive and negative infinity, positive and negative |\n | | zero, and nans, are formatted as ``inf``, ``-inf``, ``0``, |\n | | ``-0`` and ``nan`` respectively, regardless of the |\n | | precision. A precision of ``0`` is treated as equivalent |\n | | to a precision of ``1``. The default precision is ``6``. |\n +-----------+------------------------------------------------------------+\n | ``\'G\'`` | General format. Same as ``\'g\'`` except switches to ``\'E\'`` |\n | | if the number gets too large. The representations of |\n | | infinity and NaN are uppercased, too. |\n +-----------+------------------------------------------------------------+\n | ``\'n\'`` | Number. This is the same as ``\'g\'``, except that it uses |\n | | the current locale setting to insert the appropriate |\n | | number separator characters. |\n +-----------+------------------------------------------------------------+\n | ``\'%\'`` | Percentage. Multiplies the number by 100 and displays in |\n | | fixed (``\'f\'``) format, followed by a percent sign. |\n +-----------+------------------------------------------------------------+\n | None | The same as ``\'g\'``. |\n +-----------+------------------------------------------------------------+\n\n\nFormat examples\n===============\n\nThis section contains examples of the new format syntax and comparison\nwith the old ``%``-formatting.\n\nIn most of the cases the syntax is similar to the old\n``%``-formatting, with the addition of the ``{}`` and with ``:`` used\ninstead of ``%``. For example, ``\'%03.2f\'`` can be translated to\n``\'{:03.2f}\'``.\n\nThe new format syntax also supports new and different options, shown\nin the follow examples.\n\nAccessing arguments by position:\n\n >>> \'{0}, {1}, {2}\'.format(\'a\', \'b\', \'c\')\n \'a, b, c\'\n >>> \'{}, {}, {}\'.format(\'a\', \'b\', \'c\') # 2.7+ only\n \'a, b, c\'\n >>> \'{2}, {1}, {0}\'.format(\'a\', \'b\', \'c\')\n \'c, b, a\'\n >>> \'{2}, {1}, {0}\'.format(*\'abc\') # unpacking argument sequence\n \'c, b, a\'\n >>> \'{0}{1}{0}\'.format(\'abra\', \'cad\') # arguments\' indices can be repeated\n \'abracadabra\'\n\nAccessing arguments by name:\n\n >>> \'Coordinates: {latitude}, {longitude}\'.format(latitude=\'37.24N\', longitude=\'-115.81W\')\n \'Coordinates: 37.24N, -115.81W\'\n >>> coord = {\'latitude\': \'37.24N\', \'longitude\': \'-115.81W\'}\n >>> \'Coordinates: {latitude}, {longitude}\'.format(**coord)\n \'Coordinates: 37.24N, -115.81W\'\n\nAccessing arguments\' attributes:\n\n >>> c = 3-5j\n >>> (\'The complex number {0} is formed from the real part {0.real} \'\n ... \'and the imaginary part {0.imag}.\').format(c)\n \'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.\'\n >>> class Point(object):\n ... def __init__(self, x, y):\n ... self.x, self.y = x, y\n ... def __str__(self):\n ... return \'Point({self.x}, {self.y})\'.format(self=self)\n ...\n >>> str(Point(4, 2))\n \'Point(4, 2)\'\n\nAccessing arguments\' items:\n\n >>> coord = (3, 5)\n >>> \'X: {0[0]}; Y: {0[1]}\'.format(coord)\n \'X: 3; Y: 5\'\n\nReplacing ``%s`` and ``%r``:\n\n >>> "repr() shows quotes: {!r}; str() doesn\'t: {!s}".format(\'test1\', \'test2\')\n "repr() shows quotes: \'test1\'; str() doesn\'t: test2"\n\nAligning the text and specifying a width:\n\n >>> \'{:<30}\'.format(\'left aligned\')\n \'left aligned \'\n >>> \'{:>30}\'.format(\'right aligned\')\n \' right aligned\'\n >>> \'{:^30}\'.format(\'centered\')\n \' centered \'\n >>> \'{:*^30}\'.format(\'centered\') # use \'*\' as a fill char\n \'***********centered***********\'\n\nReplacing ``%+f``, ``%-f``, and ``% f`` and specifying a sign:\n\n >>> \'{:+f}; {:+f}\'.format(3.14, -3.14) # show it always\n \'+3.140000; -3.140000\'\n >>> \'{: f}; {: f}\'.format(3.14, -3.14) # show a space for positive numbers\n \' 3.140000; -3.140000\'\n >>> \'{:-f}; {:-f}\'.format(3.14, -3.14) # show only the minus -- same as \'{:f}; {:f}\'\n \'3.140000; -3.140000\'\n\nReplacing ``%x`` and ``%o`` and converting the value to different\nbases:\n\n >>> # format also supports binary numbers\n >>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)\n \'int: 42; hex: 2a; oct: 52; bin: 101010\'\n >>> # with 0x, 0o, or 0b as prefix:\n >>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)\n \'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010\'\n\nUsing the comma as a thousands separator:\n\n >>> \'{:,}\'.format(1234567890)\n \'1,234,567,890\'\n\nExpressing a percentage:\n\n >>> points = 19.5\n >>> total = 22\n >>> \'Correct answers: {:.2%}\'.format(points/total)\n \'Correct answers: 88.64%\'\n\nUsing type-specific formatting:\n\n >>> import datetime\n >>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)\n >>> \'{:%Y-%m-%d %H:%M:%S}\'.format(d)\n \'2010-07-04 12:15:58\'\n\nNesting arguments and more complex examples:\n\n >>> for align, text in zip(\'<^>\', [\'left\', \'center\', \'right\']):\n ... \'{0:{fill}{align}16}\'.format(text, fill=align, align=align)\n ...\n \'left<<<<<<<<<<<<\'\n \'^^^^^center^^^^^\'\n \'>>>>>>>>>>>right\'\n >>>\n >>> octets = [192, 168, 0, 1]\n >>> \'{:02X}{:02X}{:02X}{:02X}\'.format(*octets)\n \'C0A80001\'\n >>> int(_, 16)\n 3232235521\n >>>\n >>> width = 5\n >>> for num in range(5,12):\n ... for base in \'dXob\':\n ... print \'{0:{width}{base}}\'.format(num, base=base, width=width),\n ... print\n ...\n 5 5 5 101\n 6 6 6 110\n 7 7 7 111\n 8 8 10 1000\n 9 9 11 1001\n 10 A 12 1010\n 11 B 13 1011\n', 'function': '\nFunction definitions\n********************\n\nA function definition defines a user-defined function object (see\nsection *The standard type hierarchy*):\n\n decorated ::= decorators (classdef | funcdef)\n decorators ::= decorator+\n decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE\n funcdef ::= "def" funcname "(" [parameter_list] ")" ":" suite\n dotted_name ::= identifier ("." identifier)*\n parameter_list ::= (defparameter ",")*\n ( "*" identifier ["," "**" identifier]\n | "**" identifier\n | defparameter [","] )\n defparameter ::= parameter ["=" expression]\n sublist ::= parameter ("," parameter)* [","]\n parameter ::= identifier | "(" sublist ")"\n funcname ::= identifier\n\nA function definition is an executable statement. Its execution binds\nthe function name in the current local namespace to a function object\n(a wrapper around the executable code for the function). This\nfunction object contains a reference to the current global namespace\nas the global namespace to be used when the function is called.\n\nThe function definition does not execute the function body; this gets\nexecuted only when the function is called. [3]\n\nA function definition may be wrapped by one or more *decorator*\nexpressions. Decorator expressions are evaluated when the function is\ndefined, in the scope that contains the function definition. The\nresult must be a callable, which is invoked with the function object\nas the only argument. The returned value is bound to the function name\ninstead of the function object. Multiple decorators are applied in\nnested fashion. For example, the following code:\n\n @f1(arg)\n @f2\n def func(): pass\n\nis equivalent to:\n\n def func(): pass\n func = f1(arg)(f2(func))\n\nWhen one or more top-level *parameters* have the form *parameter*\n``=`` *expression*, the function is said to have "default parameter\nvalues." For a parameter with a default value, the corresponding\n*argument* may be omitted from a call, in which case the parameter\'s\ndefault value is substituted. If a parameter has a default value, all\nfollowing parameters must also have a default value --- this is a\nsyntactic restriction that is not expressed by the grammar.\n\n**Default parameter values are evaluated when the function definition\nis executed.** This means that the expression is evaluated once, when\nthe function is defined, and that the same "pre-computed" value is\nused for each call. This is especially important to understand when a\ndefault parameter is a mutable object, such as a list or a dictionary:\nif the function modifies the object (e.g. by appending an item to a\nlist), the default value is in effect modified. This is generally not\nwhat was intended. A way around this is to use ``None`` as the\ndefault, and explicitly test for it in the body of the function, e.g.:\n\n def whats_on_the_telly(penguin=None):\n if penguin is None:\n penguin = []\n penguin.append("property of the zoo")\n return penguin\n\nFunction call semantics are described in more detail in section\n*Calls*. A function call always assigns values to all parameters\nmentioned in the parameter list, either from position arguments, from\nkeyword arguments, or from default values. If the form\n"``*identifier``" is present, it is initialized to a tuple receiving\nany excess positional parameters, defaulting to the empty tuple. If\nthe form "``**identifier``" is present, it is initialized to a new\ndictionary receiving any excess keyword arguments, defaulting to a new\nempty dictionary.\n\nIt is also possible to create anonymous functions (functions not bound\nto a name), for immediate use in expressions. This uses lambda\nexpressions, described in section *Lambdas*. Note that the lambda\nexpression is merely a shorthand for a simplified function definition;\na function defined in a "``def``" statement can be passed around or\nassigned to another name just like a function defined by a lambda\nexpression. The "``def``" form is actually more powerful since it\nallows the execution of multiple statements.\n\n**Programmer\'s note:** Functions are first-class objects. A "``def``"\nform executed inside a function definition defines a local function\nthat can be returned or passed around. Free variables used in the\nnested function can access the local variables of the function\ncontaining the def. See section *Naming and binding* for details.\n', 'global': '\nThe ``global`` statement\n************************\n\n global_stmt ::= "global" identifier ("," identifier)*\n\nThe ``global`` statement is a declaration which holds for the entire\ncurrent code block. It means that the listed identifiers are to be\ninterpreted as globals. It would be impossible to assign to a global\nvariable without ``global``, although free variables may refer to\nglobals without being declared global.\n\nNames listed in a ``global`` statement must not be used in the same\ncode block textually preceding that ``global`` statement.\n\nNames listed in a ``global`` statement must not be defined as formal\nparameters or in a ``for`` loop control target, ``class`` definition,\nfunction definition, or ``import`` statement.\n\n**CPython implementation detail:** The current implementation does not\nenforce the latter two restrictions, but programs should not abuse\nthis freedom, as future implementations may enforce them or silently\nchange the meaning of the program.\n\n**Programmer\'s note:** the ``global`` is a directive to the parser.\nIt applies only to code parsed at the same time as the ``global``\nstatement. In particular, a ``global`` statement contained in an\n``exec`` statement does not affect the code block *containing* the\n``exec`` statement, and code contained in an ``exec`` statement is\nunaffected by ``global`` statements in the code containing the\n``exec`` statement. The same applies to the ``eval()``,\n``execfile()`` and ``compile()`` functions.\n', 'id-classes': '\nReserved classes of identifiers\n*******************************\n\nCertain classes of identifiers (besides keywords) have special\nmeanings. These classes are identified by the patterns of leading and\ntrailing underscore characters:\n\n``_*``\n Not imported by ``from module import *``. The special identifier\n ``_`` is used in the interactive interpreter to store the result of\n the last evaluation; it is stored in the ``__builtin__`` module.\n When not in interactive mode, ``_`` has no special meaning and is\n not defined. See section *The import statement*.\n\n Note: The name ``_`` is often used in conjunction with\n internationalization; refer to the documentation for the\n ``gettext`` module for more information on this convention.\n\n``__*__``\n System-defined names. These names are defined by the interpreter\n and its implementation (including the standard library). Current\n system names are discussed in the *Special method names* section\n and elsewhere. More will likely be defined in future versions of\n Python. *Any* use of ``__*__`` names, in any context, that does\n not follow explicitly documented use, is subject to breakage\n without warning.\n\n``__*``\n Class-private names. Names in this category, when used within the\n context of a class definition, are re-written to use a mangled form\n to help avoid name clashes between "private" attributes of base and\n derived classes. See section *Identifiers (Names)*.\n', @@ -52,6 +53,7 @@ 'operator-summary': '\nOperator precedence\n*******************\n\nThe following table summarizes the operator precedences in Python,\nfrom lowest precedence (least binding) to highest precedence (most\nbinding). Operators in the same box have the same precedence. Unless\nthe syntax is explicitly given, operators are binary. Operators in\nthe same box group left to right (except for comparisons, including\ntests, which all have the same precedence and chain from left to right\n--- see section *Comparisons* --- and exponentiation, which groups\nfrom right to left).\n\n+-------------------------------------------------+---------------------------------------+\n| Operator | Description |\n+=================================================+=======================================+\n| ``lambda`` | Lambda expression |\n+-------------------------------------------------+---------------------------------------+\n| ``if`` -- ``else`` | Conditional expression |\n+-------------------------------------------------+---------------------------------------+\n| ``or`` | Boolean OR |\n+-------------------------------------------------+---------------------------------------+\n| ``and`` | Boolean AND |\n+-------------------------------------------------+---------------------------------------+\n| ``not`` ``x`` | Boolean NOT |\n+-------------------------------------------------+---------------------------------------+\n| ``in``, ``not in``, ``is``, ``is not``, ``<``, | Comparisons, including membership |\n| ``<=``, ``>``, ``>=``, ``<>``, ``!=``, ``==`` | tests and identity tests |\n+-------------------------------------------------+---------------------------------------+\n| ``|`` | Bitwise OR |\n+-------------------------------------------------+---------------------------------------+\n| ``^`` | Bitwise XOR |\n+-------------------------------------------------+---------------------------------------+\n| ``&`` | Bitwise AND |\n+-------------------------------------------------+---------------------------------------+\n| ``<<``, ``>>`` | Shifts |\n+-------------------------------------------------+---------------------------------------+\n| ``+``, ``-`` | Addition and subtraction |\n+-------------------------------------------------+---------------------------------------+\n| ``*``, ``/``, ``//``, ``%`` | Multiplication, division, remainder |\n| | [8] |\n+-------------------------------------------------+---------------------------------------+\n| ``+x``, ``-x``, ``~x`` | Positive, negative, bitwise NOT |\n+-------------------------------------------------+---------------------------------------+\n| ``**`` | Exponentiation [9] |\n+-------------------------------------------------+---------------------------------------+\n| ``x[index]``, ``x[index:index]``, | Subscription, slicing, call, |\n| ``x(arguments...)``, ``x.attribute`` | attribute reference |\n+-------------------------------------------------+---------------------------------------+\n| ``(expressions...)``, ``[expressions...]``, | Binding or tuple display, list |\n| ``{key: value...}``, ```expressions...``` | display, dictionary display, string |\n| | conversion |\n+-------------------------------------------------+---------------------------------------+\n\n-[ Footnotes ]-\n\n[1] In Python 2.3 and later releases, a list comprehension "leaks" the\n control variables of each ``for`` it contains into the containing\n scope. However, this behavior is deprecated, and relying on it\n will not work in Python 3.\n\n[2] While ``abs(x%y) < abs(y)`` is true mathematically, for floats it\n may not be true numerically due to roundoff. For example, and\n assuming a platform on which a Python float is an IEEE 754 double-\n precision number, in order that ``-1e-100 % 1e100`` have the same\n sign as ``1e100``, the computed result is ``-1e-100 + 1e100``,\n which is numerically exactly equal to ``1e100``. The function\n ``math.fmod()`` returns a result whose sign matches the sign of\n the first argument instead, and so returns ``-1e-100`` in this\n case. Which approach is more appropriate depends on the\n application.\n\n[3] If x is very close to an exact integer multiple of y, it\'s\n possible for ``floor(x/y)`` to be one larger than ``(x-x%y)/y``\n due to rounding. In such cases, Python returns the latter result,\n in order to preserve that ``divmod(x,y)[0] * y + x % y`` be very\n close to ``x``.\n\n[4] While comparisons between unicode strings make sense at the byte\n level, they may be counter-intuitive to users. For example, the\n strings ``u"\\u00C7"`` and ``u"\\u0043\\u0327"`` compare differently,\n even though they both represent the same unicode character (LATIN\n CAPITAL LETTER C WITH CEDILLA). To compare strings in a human\n recognizable way, compare using ``unicodedata.normalize()``.\n\n[5] The implementation computes this efficiently, without constructing\n lists or sorting.\n\n[6] Earlier versions of Python used lexicographic comparison of the\n sorted (key, value) lists, but this was very expensive for the\n common case of comparing for equality. An even earlier version of\n Python compared dictionaries by identity only, but this caused\n surprises because people expected to be able to test a dictionary\n for emptiness by comparing it to ``{}``.\n\n[7] Due to automatic garbage-collection, free lists, and the dynamic\n nature of descriptors, you may notice seemingly unusual behaviour\n in certain uses of the ``is`` operator, like those involving\n comparisons between instance methods, or constants. Check their\n documentation for more info.\n\n[8] The ``%`` operator is also used for string formatting; the same\n precedence applies.\n\n[9] The power operator ``**`` binds less tightly than an arithmetic or\n bitwise unary operator on its right, that is, ``2**-1`` is\n ``0.5``.\n', 'pass': '\nThe ``pass`` statement\n**********************\n\n pass_stmt ::= "pass"\n\n``pass`` is a null operation --- when it is executed, nothing happens.\nIt is useful as a placeholder when a statement is required\nsyntactically, but no code needs to be executed, for example:\n\n def f(arg): pass # a function that does nothing (yet)\n\n class C: pass # a class with no methods (yet)\n', 'power': '\nThe power operator\n******************\n\nThe power operator binds more tightly than unary operators on its\nleft; it binds less tightly than unary operators on its right. The\nsyntax is:\n\n power ::= primary ["**" u_expr]\n\nThus, in an unparenthesized sequence of power and unary operators, the\noperators are evaluated from right to left (this does not constrain\nthe evaluation order for the operands): ``-1**2`` results in ``-1``.\n\nThe power operator has the same semantics as the built-in ``pow()``\nfunction, when called with two arguments: it yields its left argument\nraised to the power of its right argument. The numeric arguments are\nfirst converted to a common type. The result type is that of the\narguments after coercion.\n\nWith mixed operand types, the coercion rules for binary arithmetic\noperators apply. For int and long int operands, the result has the\nsame type as the operands (after coercion) unless the second argument\nis negative; in that case, all arguments are converted to float and a\nfloat result is delivered. For example, ``10**2`` returns ``100``, but\n``10**-2`` returns ``0.01``. (This last feature was added in Python\n2.2. In Python 2.1 and before, if both arguments were of integer types\nand the second argument was negative, an exception was raised).\n\nRaising ``0.0`` to a negative power results in a\n``ZeroDivisionError``. Raising a negative number to a fractional power\nresults in a ``ValueError``.\n', + 'print': '\nThe ``print`` statement\n***********************\n\n print_stmt ::= "print" ([expression ("," expression)* [","]]\n | ">>" expression [("," expression)+ [","]])\n\n``print`` evaluates each expression in turn and writes the resulting\nobject to standard output (see below). If an object is not a string,\nit is first converted to a string using the rules for string\nconversions. The (resulting or original) string is then written. A\nspace is written before each object is (converted and) written, unless\nthe output system believes it is positioned at the beginning of a\nline. This is the case (1) when no characters have yet been written\nto standard output, (2) when the last character written to standard\noutput is a whitespace character except ``\' \'``, or (3) when the last\nwrite operation on standard output was not a ``print`` statement. (In\nsome cases it may be functional to write an empty string to standard\noutput for this reason.)\n\nNote: Objects which act like file objects but which are not the built-in\n file objects often do not properly emulate this aspect of the file\n object\'s behavior, so it is best not to rely on this.\n\nA ``\'\\n\'`` character is written at the end, unless the ``print``\nstatement ends with a comma. This is the only action if the statement\ncontains just the keyword ``print``.\n\nStandard output is defined as the file object named ``stdout`` in the\nbuilt-in module ``sys``. If no such object exists, or if it does not\nhave a ``write()`` method, a ``RuntimeError`` exception is raised.\n\n``print`` also has an extended form, defined by the second portion of\nthe syntax described above. This form is sometimes referred to as\n"``print`` chevron." In this form, the first expression after the\n``>>`` must evaluate to a "file-like" object, specifically an object\nthat has a ``write()`` method as described above. With this extended\nform, the subsequent expressions are printed to this file object. If\nthe first expression evaluates to ``None``, then ``sys.stdout`` is\nused as the file for output.\n', 'raise': '\nThe ``raise`` statement\n***********************\n\n raise_stmt ::= "raise" [expression ["," expression ["," expression]]]\n\nIf no expressions are present, ``raise`` re-raises the last exception\nthat was active in the current scope. If no exception is active in\nthe current scope, a ``TypeError`` exception is raised indicating that\nthis is an error (if running under IDLE, a ``Queue.Empty`` exception\nis raised instead).\n\nOtherwise, ``raise`` evaluates the expressions to get three objects,\nusing ``None`` as the value of omitted expressions. The first two\nobjects are used to determine the *type* and *value* of the exception.\n\nIf the first object is an instance, the type of the exception is the\nclass of the instance, the instance itself is the value, and the\nsecond object must be ``None``.\n\nIf the first object is a class, it becomes the type of the exception.\nThe second object is used to determine the exception value: If it is\nan instance of the class, the instance becomes the exception value. If\nthe second object is a tuple, it is used as the argument list for the\nclass constructor; if it is ``None``, an empty argument list is used,\nand any other object is treated as a single argument to the\nconstructor. The instance so created by calling the constructor is\nused as the exception value.\n\nIf a third object is present and not ``None``, it must be a traceback\nobject (see section *The standard type hierarchy*), and it is\nsubstituted instead of the current location as the place where the\nexception occurred. If the third object is present and not a\ntraceback object or ``None``, a ``TypeError`` exception is raised.\nThe three-expression form of ``raise`` is useful to re-raise an\nexception transparently in an except clause, but ``raise`` with no\nexpressions should be preferred if the exception to be re-raised was\nthe most recently active exception in the current scope.\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information about handling exceptions is in section\n*The try statement*.\n', 'return': '\nThe ``return`` statement\n************************\n\n return_stmt ::= "return" [expression_list]\n\n``return`` may only occur syntactically nested in a function\ndefinition, not within a nested class definition.\n\nIf an expression list is present, it is evaluated, else ``None`` is\nsubstituted.\n\n``return`` leaves the current function call with the expression list\n(or ``None``) as return value.\n\nWhen ``return`` passes control out of a ``try`` statement with a\n``finally`` clause, that ``finally`` clause is executed before really\nleaving the function.\n\nIn a generator function, the ``return`` statement is not allowed to\ninclude an ``expression_list``. In that context, a bare ``return``\nindicates that the generator is done and will cause ``StopIteration``\nto be raised.\n', 'sequence-types': "\nEmulating container types\n*************************\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which ``0 <= k < N``\nwhere *N* is the length of the sequence, or slice objects, which\ndefine a range of items. (For backwards compatibility, the method\n``__getslice__()`` (see below) can also be defined to handle simple,\nbut not extended slices.) It is also recommended that mappings provide\nthe methods ``keys()``, ``values()``, ``items()``, ``has_key()``,\n``get()``, ``clear()``, ``setdefault()``, ``iterkeys()``,\n``itervalues()``, ``iteritems()``, ``pop()``, ``popitem()``,\n``copy()``, and ``update()`` behaving similar to those for Python's\nstandard dictionary objects. The ``UserDict`` module provides a\n``DictMixin`` class to help create those methods from a base set of\n``__getitem__()``, ``__setitem__()``, ``__delitem__()``, and\n``keys()``. Mutable sequences should provide methods ``append()``,\n``count()``, ``index()``, ``extend()``, ``insert()``, ``pop()``,\n``remove()``, ``reverse()`` and ``sort()``, like Python standard list\nobjects. Finally, sequence types should implement addition (meaning\nconcatenation) and multiplication (meaning repetition) by defining the\nmethods ``__add__()``, ``__radd__()``, ``__iadd__()``, ``__mul__()``,\n``__rmul__()`` and ``__imul__()`` described below; they should not\ndefine ``__coerce__()`` or other numerical operators. It is\nrecommended that both mappings and sequences implement the\n``__contains__()`` method to allow efficient use of the ``in``\noperator; for mappings, ``in`` should be equivalent of ``has_key()``;\nfor sequences, it should search through the values. It is further\nrecommended that both mappings and sequences implement the\n``__iter__()`` method to allow efficient iteration through the\ncontainer; for mappings, ``__iter__()`` should be the same as\n``iterkeys()``; for sequences, it should iterate through the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function ``len()``. Should return\n the length of the object, an integer ``>=`` 0. Also, an object\n that doesn't define a ``__nonzero__()`` method and whose\n ``__len__()`` method returns zero is considered to be false in a\n Boolean context.\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of ``self[key]``. For sequence\n types, the accepted keys should be integers and slice objects.\n Note that the special interpretation of negative indexes (if the\n class wishes to emulate a sequence type) is up to the\n ``__getitem__()`` method. If *key* is of an inappropriate type,\n ``TypeError`` may be raised; if of a value outside the set of\n indexes for the sequence (after any special interpretation of\n negative values), ``IndexError`` should be raised. For mapping\n types, if *key* is missing (not in the container), ``KeyError``\n should be raised.\n\n Note: ``for`` loops expect that an ``IndexError`` will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to ``self[key]``. Same note as for\n ``__getitem__()``. This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the ``__getitem__()`` method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of ``self[key]``. Same note as for\n ``__getitem__()``. This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the ``__getitem__()``\n method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container, and should also be made\n available as the method ``iterkeys()``.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the ``reversed()`` built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the ``__reversed__()`` method is not provided, the\n ``reversed()`` built-in will fall back to using the sequence\n protocol (``__len__()`` and ``__getitem__()``). Objects that\n support the sequence protocol should only provide\n ``__reversed__()`` if they can provide an implementation that is\n more efficient than the one provided by ``reversed()``.\n\n New in version 2.6.\n\nThe membership test operators (``in`` and ``not in``) are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don't define ``__contains__()``, the membership\n test first tries iteration via ``__iter__()``, then the old\n sequence iteration protocol via ``__getitem__()``, see *this\n section in the language reference*.\n", @@ -64,13 +66,13 @@ 'subscriptions': '\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object of a sequence or mapping type.\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to a\nplain integer. If this value is negative, the length of the sequence\nis added to it (so that, e.g., ``x[-1]`` selects the last item of\n``x``.) The resulting value must be a nonnegative integer less than\nthe number of items in the sequence, and the subscription selects the\nitem whose index is that value (counting from zero).\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n', 'truth': "\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an ``if`` or\n``while`` condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* ``None``\n\n* ``False``\n\n* zero of any numeric type, for example, ``0``, ``0L``, ``0.0``,\n ``0j``.\n\n* any empty sequence, for example, ``''``, ``()``, ``[]``.\n\n* any empty mapping, for example, ``{}``.\n\n* instances of user-defined classes, if the class defines a\n ``__nonzero__()`` or ``__len__()`` method, when that method returns\n the integer zero or ``bool`` value ``False``. [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn ``0`` or ``False`` for false and ``1`` or ``True`` for true,\nunless otherwise stated. (Important exception: the Boolean operations\n``or`` and ``and`` always return one of their operands.)\n", 'try': '\nThe ``try`` statement\n*********************\n\nThe ``try`` statement specifies exception handlers and/or cleanup code\nfor a group of statements:\n\n try_stmt ::= try1_stmt | try2_stmt\n try1_stmt ::= "try" ":" suite\n ("except" [expression [("as" | ",") target]] ":" suite)+\n ["else" ":" suite]\n ["finally" ":" suite]\n try2_stmt ::= "try" ":" suite\n "finally" ":" suite\n\nChanged in version 2.5: In previous versions of Python,\n``try``...``except``...``finally`` did not work. ``try``...``except``\nhad to be nested in ``try``...``finally``.\n\nThe ``except`` clause(s) specify one or more exception handlers. When\nno exception occurs in the ``try`` clause, no exception handler is\nexecuted. When an exception occurs in the ``try`` suite, a search for\nan exception handler is started. This search inspects the except\nclauses in turn until one is found that matches the exception. An\nexpression-less except clause, if present, must be last; it matches\nany exception. For an except clause with an expression, that\nexpression is evaluated, and the clause matches the exception if the\nresulting object is "compatible" with the exception. An object is\ncompatible with an exception if it is the class or a base class of the\nexception object, or a tuple containing an item compatible with the\nexception.\n\nIf no except clause matches the exception, the search for an exception\nhandler continues in the surrounding code and on the invocation stack.\n[1]\n\nIf the evaluation of an expression in the header of an except clause\nraises an exception, the original search for a handler is canceled and\na search starts for the new exception in the surrounding code and on\nthe call stack (it is treated as if the entire ``try`` statement\nraised the exception).\n\nWhen a matching except clause is found, the exception is assigned to\nthe target specified in that except clause, if present, and the except\nclause\'s suite is executed. All except clauses must have an\nexecutable block. When the end of this block is reached, execution\ncontinues normally after the entire try statement. (This means that\nif two nested handlers exist for the same exception, and the exception\noccurs in the try clause of the inner handler, the outer handler will\nnot handle the exception.)\n\nBefore an except clause\'s suite is executed, details about the\nexception are assigned to three variables in the ``sys`` module:\n``sys.exc_type`` receives the object identifying the exception;\n``sys.exc_value`` receives the exception\'s parameter;\n``sys.exc_traceback`` receives a traceback object (see section *The\nstandard type hierarchy*) identifying the point in the program where\nthe exception occurred. These details are also available through the\n``sys.exc_info()`` function, which returns a tuple ``(exc_type,\nexc_value, exc_traceback)``. Use of the corresponding variables is\ndeprecated in favor of this function, since their use is unsafe in a\nthreaded program. As of Python 1.5, the variables are restored to\ntheir previous values (before the call) when returning from a function\nthat handled an exception.\n\nThe optional ``else`` clause is executed if and when control flows off\nthe end of the ``try`` clause. [2] Exceptions in the ``else`` clause\nare not handled by the preceding ``except`` clauses.\n\nIf ``finally`` is present, it specifies a \'cleanup\' handler. The\n``try`` clause is executed, including any ``except`` and ``else``\nclauses. If an exception occurs in any of the clauses and is not\nhandled, the exception is temporarily saved. The ``finally`` clause is\nexecuted. If there is a saved exception, it is re-raised at the end\nof the ``finally`` clause. If the ``finally`` clause raises another\nexception or executes a ``return`` or ``break`` statement, the saved\nexception is discarded:\n\n def f():\n try:\n 1/0\n finally:\n return 42\n\n >>> f()\n 42\n\nThe exception information is not available to the program during\nexecution of the ``finally`` clause.\n\nWhen a ``return``, ``break`` or ``continue`` statement is executed in\nthe ``try`` suite of a ``try``...``finally`` statement, the\n``finally`` clause is also executed \'on the way out.\' A ``continue``\nstatement is illegal in the ``finally`` clause. (The reason is a\nproblem with the current implementation --- this restriction may be\nlifted in the future).\n\nAdditional information on exceptions can be found in section\n*Exceptions*, and information on using the ``raise`` statement to\ngenerate exceptions may be found in section *The raise statement*.\n', - 'types': '\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.).\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name ``None``.\n It is used to signify the absence of a value in many situations,\n e.g., it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n ``NotImplemented``. Numeric methods and rich comparison methods may\n return this value if they do not implement the operation for the\n operands provided. (The interpreter will then try the reflected\n operation, or some other fallback, depending on the operator.) Its\n truth value is true.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n ``Ellipsis``. It is used to indicate the presence of the ``...``\n syntax in a slice. Its truth value is true.\n\n``numbers.Number``\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n ``numbers.Integral``\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are three types of integers:\n\n Plain integers\n These represent numbers in the range -2147483648 through\n 2147483647. (The range may be larger on machines with a\n larger natural word size, but not smaller.) When the result\n of an operation would fall outside this range, the result is\n normally returned as a long integer (in some cases, the\n exception ``OverflowError`` is raised instead). For the\n purpose of shift and mask operations, integers are assumed to\n have a binary, 2\'s complement notation using 32 or more bits,\n and hiding no bits from the user (i.e., all 4294967296\n different bit patterns correspond to different values).\n\n Long integers\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans\n These represent the truth values False and True. The two\n objects representing the values False and True are the only\n Boolean objects. The Boolean type is a subtype of plain\n integers, and Boolean values behave like the values 0 and 1,\n respectively, in almost all contexts, the exception being\n that when converted to a string, the strings ``"False"`` or\n ``"True"`` are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers and the least surprises when\n switching between the plain and long integer domains. Any\n operation, if it yields a result in the plain integer domain,\n will yield the same result in the long integer domain or when\n using mixed operands. The switch between domains is transparent\n to the programmer.\n\n ``numbers.Real`` (``float``)\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these is\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n ``numbers.Complex``\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number ``z`` can be retrieved through the read-only\n attributes ``z.real`` and ``z.imag``.\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function ``len()`` returns the number of\n items of a sequence. When the length of a sequence is *n*, the\n index set contains the numbers 0, 1, ..., *n*-1. Item *i* of\n sequence *a* is selected by ``a[i]``.\n\n Sequences also support slicing: ``a[i:j]`` selects all items with\n index *k* such that *i* ``<=`` *k* ``<`` *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: ``a[i:j:k]`` selects all items of *a* with index *x*\n where ``x = i + n*k``, *n* ``>=`` ``0`` and *i* ``<=`` *x* ``<``\n *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n The items of a string are characters. There is no separate\n character type; a character is represented by a string of one\n item. Characters represent (at least) 8-bit bytes. The\n built-in functions ``chr()`` and ``ord()`` convert between\n characters and nonnegative integers representing the byte\n values. Bytes with the values 0-127 usually represent the\n corresponding ASCII values, but the interpretation of values\n is up to the program. The string data type is also used to\n represent arrays of bytes, e.g., to hold data read from a\n file.\n\n (On systems whose native character set is not ASCII, strings\n may use EBCDIC in their internal representation, provided the\n functions ``chr()`` and ``ord()`` implement a mapping between\n ASCII and EBCDIC, and string comparison preserves the ASCII\n order. Or perhaps someone can propose a better rule?)\n\n Unicode\n The items of a Unicode object are Unicode code units. A\n Unicode code unit is represented by a Unicode object of one\n item and can hold either a 16-bit or 32-bit value\n representing a Unicode ordinal (the maximum value for the\n ordinal is given in ``sys.maxunicode``, and depends on how\n Python is configured at compile time). Surrogate pairs may\n be present in the Unicode object, and will be reported as two\n separate items. The built-in functions ``unichr()`` and\n ``ord()`` convert between code units and nonnegative integers\n representing the Unicode ordinals as defined in the Unicode\n Standard 3.0. Conversion from and to other encodings are\n possible through the Unicode method ``encode()`` and the\n built-in function ``unicode()``.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and ``del`` (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in ``bytearray()`` constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module ``array`` provides an additional example of\n a mutable sequence type.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function ``len()``\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., ``1`` and\n ``1.0``), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n ``set()`` constructor and can be modified afterwards by several\n methods, such as ``add()``.\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in ``frozenset()`` constructor. As a frozenset is\n immutable and *hashable*, it can be used again as an element of\n another set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation ``a[k]`` selects the item indexed by\n ``k`` from the mapping ``a``; this can be used in expressions and\n as the target of assignments or ``del`` statements. The built-in\n function ``len()`` returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., ``1`` and\n ``1.0``) then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the ``{...}``\n notation (see section *Dictionary displays*).\n\n The extension modules ``dbm``, ``gdbm``, and ``bsddb`` provide\n additional examples of mapping types.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +-------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +=========================+=================================+=============+\n | ``func_doc`` | The function\'s documentation | Writable |\n | | string, or ``None`` if | |\n | | unavailable | |\n +-------------------------+---------------------------------+-------------+\n | ``__doc__`` | Another way of spelling | Writable |\n | | ``func_doc`` | |\n +-------------------------+---------------------------------+-------------+\n | ``func_name`` | The function\'s name | Writable |\n +-------------------------+---------------------------------+-------------+\n | ``__name__`` | Another way of spelling | Writable |\n | | ``func_name`` | |\n +-------------------------+---------------------------------+-------------+\n | ``__module__`` | The name of the module the | Writable |\n | | function was defined in, or | |\n | | ``None`` if unavailable. | |\n +-------------------------+---------------------------------+-------------+\n | ``func_defaults`` | A tuple containing default | Writable |\n | | argument values for those | |\n | | arguments that have defaults, | |\n | | or ``None`` if no arguments | |\n | | have a default value | |\n +-------------------------+---------------------------------+-------------+\n | ``func_code`` | The code object representing | Writable |\n | | the compiled function body. | |\n +-------------------------+---------------------------------+-------------+\n | ``func_globals`` | A reference to the dictionary | Read-only |\n | | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +-------------------------+---------------------------------+-------------+\n | ``func_dict`` | The namespace supporting | Writable |\n | | arbitrary function attributes. | |\n +-------------------------+---------------------------------+-------------+\n | ``func_closure`` | ``None`` or a tuple of cells | Read-only |\n | | that contain bindings for the | |\n | | function\'s free variables. | |\n +-------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Changed in version 2.4: ``func_name`` is now writable.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n User-defined methods\n A user-defined method object combines a class, a class instance\n (or ``None``) and any callable object (normally a user-defined\n function).\n\n Special read-only attributes: ``im_self`` is the class instance\n object, ``im_func`` is the function object; ``im_class`` is the\n class of ``im_self`` for bound methods or the class that asked\n for the method for unbound methods; ``__doc__`` is the method\'s\n documentation (same as ``im_func.__doc__``); ``__name__`` is the\n method name (same as ``im_func.__name__``); ``__module__`` is\n the name of the module the method was defined in, or ``None`` if\n unavailable.\n\n Changed in version 2.2: ``im_self`` used to refer to the class\n that defined the method.\n\n Changed in version 2.6: For Python 3 forward-compatibility,\n ``im_func`` is also available as ``__func__``, and ``im_self``\n as ``__self__``.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object, an unbound\n user-defined method object, or a class method object. When the\n attribute is a user-defined method object, a new method object\n is only created if the class from which it is being retrieved is\n the same as, or a derived class of, the class stored in the\n original method object; otherwise, the original method object is\n used as it is.\n\n When a user-defined method object is created by retrieving a\n user-defined function object from a class, its ``im_self``\n attribute is ``None`` and the method object is said to be\n unbound. When one is created by retrieving a user-defined\n function object from a class via one of its instances, its\n ``im_self`` attribute is the instance, and the method object is\n said to be bound. In either case, the new method\'s ``im_class``\n attribute is the class from which the retrieval takes place, and\n its ``im_func`` attribute is the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the ``im_func``\n attribute of the new instance is not the original method object\n but its ``im_func`` attribute.\n\n When a user-defined method object is created by retrieving a\n class method object from a class or instance, its ``im_self``\n attribute is the class itself, and its ``im_func`` attribute is\n the function object underlying the class method.\n\n When an unbound user-defined method object is called, the\n underlying function (``im_func``) is called, with the\n restriction that the first argument must be an instance of the\n proper class (``im_class``) or of a derived class thereof.\n\n When a bound user-defined method object is called, the\n underlying function (``im_func``) is called, inserting the class\n instance (``im_self``) in front of the argument list. For\n instance, when ``C`` is a class which contains a definition for\n a function ``f()``, and ``x`` is an instance of ``C``, calling\n ``x.f(1)`` is equivalent to calling ``C.f(x, 1)``.\n\n When a user-defined method object is derived from a class method\n object, the "class instance" stored in ``im_self`` will actually\n be the class itself, so that calling either ``x.f(1)`` or\n ``C.f(1)`` is equivalent to calling ``f(C,1)`` where ``f`` is\n the underlying function.\n\n Note that the transformation from function object to (unbound or\n bound) method object happens each time the attribute is\n retrieved from the class or instance. In some cases, a fruitful\n optimization is to assign the attribute to a local variable and\n call that local variable. Also notice that this transformation\n only happens for user-defined functions; other callable objects\n (and all non-callable objects) are retrieved without\n transformation. It is also important to note that user-defined\n functions which are attributes of a class instance are not\n converted to bound methods; this *only* happens when the\n function is an attribute of the class.\n\n Generator functions\n A function or method which uses the ``yield`` statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s ``next()`` method will cause the function to\n execute until it provides a value using the ``yield`` statement.\n When the function executes a ``return`` statement or falls off\n the end, a ``StopIteration`` exception is raised and the\n iterator will have reached the end of the set of values to be\n returned.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are ``len()`` and ``math.sin()``\n (``math`` is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: ``__doc__`` is the function\'s documentation\n string, or ``None`` if unavailable; ``__name__`` is the\n function\'s name; ``__self__`` is set to ``None`` (but see the\n next item); ``__module__`` is the name of the module the\n function was defined in or ``None`` if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n ``alist.append()``, assuming *alist* is a list object. In this\n case, the special read-only attribute ``__self__`` is set to the\n object denoted by *alist*.\n\n Class Types\n Class types, or "new-style classes," are callable. These\n objects normally act as factories for new instances of\n themselves, but variations are possible for class types that\n override ``__new__()``. The arguments of the call are passed to\n ``__new__()`` and, in the typical case, to ``__init__()`` to\n initialize the new instance.\n\n Classic Classes\n Class objects are described below. When a class object is\n called, a new class instance (also described below) is created\n and returned. This implies a call to the class\'s ``__init__()``\n method if it has one. Any arguments are passed on to the\n ``__init__()`` method. If there is no ``__init__()`` method,\n the class must be called without arguments.\n\n Class instances\n Class instances are described below. Class instances are\n callable only when the class has a ``__call__()`` method;\n ``x(arguments)`` is a shorthand for ``x.__call__(arguments)``.\n\nModules\n Modules are imported by the ``import`` statement (see section *The\n import statement*). A module object has a namespace implemented by\n a dictionary object (this is the dictionary referenced by the\n func_globals attribute of functions defined in the module).\n Attribute references are translated to lookups in this dictionary,\n e.g., ``m.x`` is equivalent to ``m.__dict__["x"]``. A module object\n does not contain the code object used to initialize the module\n (since it isn\'t needed once the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., ``m.x = 1`` is equivalent to ``m.__dict__["x"] = 1``.\n\n Special read-only attribute: ``__dict__`` is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: ``__name__`` is the module\'s\n name; ``__doc__`` is the module\'s documentation string, or ``None``\n if unavailable; ``__file__`` is the pathname of the file from which\n the module was loaded, if it was loaded from a file. The\n ``__file__`` attribute is not present for C modules that are\n statically linked into the interpreter; for extension modules\n loaded dynamically from a shared library, it is the pathname of the\n shared library file.\n\nClasses\n Both class types (new-style classes) and class objects (old-\n style/classic classes) are typically created by class definitions\n (see section *Class definitions*). A class has a namespace\n implemented by a dictionary object. Class attribute references are\n translated to lookups in this dictionary, e.g., ``C.x`` is\n translated to ``C.__dict__["x"]`` (although for new-style classes\n in particular there are a number of hooks which allow for other\n means of locating attributes). When the attribute name is not found\n there, the attribute search continues in the base classes. For\n old-style classes, the search is depth-first, left-to-right in the\n order of occurrence in the base class list. New-style classes use\n the more complex C3 method resolution order which behaves correctly\n even in the presence of \'diamond\' inheritance structures where\n there are multiple inheritance paths leading back to a common\n ancestor. Additional details on the C3 MRO used by new-style\n classes can be found in the documentation accompanying the 2.3\n release at http://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class ``C``, say) would yield\n a user-defined function object or an unbound user-defined method\n object whose associated class is either ``C`` or one of its base\n classes, it is transformed into an unbound user-defined method\n object whose ``im_class`` attribute is ``C``. When it would yield a\n class method object, it is transformed into a bound user-defined\n method object whose ``im_self`` attribute is ``C``. When it would\n yield a static method object, it is transformed into the object\n wrapped by the static method object. See section *Implementing\n Descriptors* for another way in which attributes retrieved from a\n class may differ from those actually contained in its ``__dict__``\n (note that only new-style classes support descriptors).\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: ``__name__`` is the class name; ``__module__``\n is the module name in which the class was defined; ``__dict__`` is\n the dictionary containing the class\'s namespace; ``__bases__`` is a\n tuple (possibly empty or a singleton) containing the base classes,\n in the order of their occurrence in the base class list;\n ``__doc__`` is the class\'s documentation string, or None if\n undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object or an unbound user-defined method object whose\n associated class is the class (call it ``C``) of the instance for\n which the attribute reference was initiated or one of its bases, it\n is transformed into a bound user-defined method object whose\n ``im_class`` attribute is ``C`` and whose ``im_self`` attribute is\n the instance. Static method and class method objects are also\n transformed, as if they had been retrieved from class ``C``; see\n above under "Classes". See section *Implementing Descriptors* for\n another way in which attributes of a class retrieved via its\n instances may differ from the objects actually stored in the\n class\'s ``__dict__``. If no class attribute is found, and the\n object\'s class has a ``__getattr__()`` method, that is called to\n satisfy the lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n ``__setattr__()`` or ``__delattr__()`` method, this is called\n instead of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: ``__dict__`` is the attribute dictionary;\n ``__class__`` is the instance\'s class.\n\nFiles\n A file object represents an open file. File objects are created by\n the ``open()`` built-in function, and also by ``os.popen()``,\n ``os.fdopen()``, and the ``makefile()`` method of socket objects\n (and perhaps by other functions or methods provided by extension\n modules). The objects ``sys.stdin``, ``sys.stdout`` and\n ``sys.stderr`` are initialized to file objects corresponding to the\n interpreter\'s standard input, output and error streams. See *File\n Objects* for complete documentation of file objects.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: ``co_name`` gives the function\n name; ``co_argcount`` is the number of positional arguments\n (including arguments with default values); ``co_nlocals`` is the\n number of local variables used by the function (including\n arguments); ``co_varnames`` is a tuple containing the names of\n the local variables (starting with the argument names);\n ``co_cellvars`` is a tuple containing the names of local\n variables that are referenced by nested functions;\n ``co_freevars`` is a tuple containing the names of free\n variables; ``co_code`` is a string representing the sequence of\n bytecode instructions; ``co_consts`` is a tuple containing the\n literals used by the bytecode; ``co_names`` is a tuple\n containing the names used by the bytecode; ``co_filename`` is\n the filename from which the code was compiled;\n ``co_firstlineno`` is the first line number of the function;\n ``co_lnotab`` is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); ``co_stacksize`` is the required stack size\n (including local variables); ``co_flags`` is an integer encoding\n a number of flags for the interpreter.\n\n The following flag bits are defined for ``co_flags``: bit\n ``0x04`` is set if the function uses the ``*arguments`` syntax\n to accept an arbitrary number of positional arguments; bit\n ``0x08`` is set if the function uses the ``**keywords`` syntax\n to accept arbitrary keyword arguments; bit ``0x20`` is set if\n the function is a generator.\n\n Future feature declarations (``from __future__ import\n division``) also use bits in ``co_flags`` to indicate whether a\n code object was compiled with a particular feature enabled: bit\n ``0x2000`` is set if the function was compiled with future\n division enabled; bits ``0x10`` and ``0x1000`` were used in\n earlier versions of Python.\n\n Other bits in ``co_flags`` are reserved for internal use.\n\n If a code object represents a function, the first item in\n ``co_consts`` is the documentation string of the function, or\n ``None`` if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: ``f_back`` is to the previous\n stack frame (towards the caller), or ``None`` if this is the\n bottom stack frame; ``f_code`` is the code object being executed\n in this frame; ``f_locals`` is the dictionary used to look up\n local variables; ``f_globals`` is used for global variables;\n ``f_builtins`` is used for built-in (intrinsic) names;\n ``f_restricted`` is a flag indicating whether the function is\n executing in restricted execution mode; ``f_lasti`` gives the\n precise instruction (this is an index into the bytecode string\n of the code object).\n\n Special writable attributes: ``f_trace``, if not ``None``, is a\n function called at the start of each source code line (this is\n used by the debugger); ``f_exc_type``, ``f_exc_value``,\n ``f_exc_traceback`` represent the last exception raised in the\n parent frame provided another exception was ever raised in the\n current frame (in all other cases they are None); ``f_lineno``\n is the current line number of the frame --- writing to this from\n within a trace function jumps to the given line (only for the\n bottom-most frame). A debugger can implement a Jump command\n (aka Set Next Statement) by writing to f_lineno.\n\n Traceback objects\n Traceback objects represent a stack trace of an exception. A\n traceback object is created when an exception occurs. When the\n search for an exception handler unwinds the execution stack, at\n each unwound level a traceback object is inserted in front of\n the current traceback. When an exception handler is entered,\n the stack trace is made available to the program. (See section\n *The try statement*.) It is accessible as ``sys.exc_traceback``,\n and also as the third item of the tuple returned by\n ``sys.exc_info()``. The latter is the preferred interface,\n since it works correctly when the program is using multiple\n threads. When the program contains no suitable handler, the\n stack trace is written (nicely formatted) to the standard error\n stream; if the interpreter is interactive, it is also made\n available to the user as ``sys.last_traceback``.\n\n Special read-only attributes: ``tb_next`` is the next level in\n the stack trace (towards the frame where the exception\n occurred), or ``None`` if there is no next level; ``tb_frame``\n points to the execution frame of the current level;\n ``tb_lineno`` gives the line number where the exception\n occurred; ``tb_lasti`` indicates the precise instruction. The\n line number and last instruction in the traceback may differ\n from the line number of its frame object if the exception\n occurred in a ``try`` statement with no matching except clause\n or with a finally clause.\n\n Slice objects\n Slice objects are used to represent slices when *extended slice\n syntax* is used. This is a slice using two colons, or multiple\n slices or ellipses separated by commas, e.g., ``a[i:j:step]``,\n ``a[i:j, k:l]``, or ``a[..., i:j]``. They are also created by\n the built-in ``slice()`` function.\n\n Special read-only attributes: ``start`` is the lower bound;\n ``stop`` is the upper bound; ``step`` is the step value; each is\n ``None`` if omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the extended slice that the slice\n object would describe if applied to a sequence of *length*\n items. It returns a tuple of three integers; respectively\n these are the *start* and *stop* indices and the *step* or\n stride length of the slice. Missing or out-of-bounds indices\n are handled in a manner consistent with regular slices.\n\n New in version 2.3.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n ``staticmethod()`` constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in ``classmethod()`` constructor.\n', + 'types': '\nThe standard type hierarchy\n***************************\n\nBelow is a list of the types that are built into Python. Extension\nmodules (written in C, Java, or other languages, depending on the\nimplementation) can define additional types. Future versions of\nPython may add types to the type hierarchy (e.g., rational numbers,\nefficiently stored arrays of integers, etc.).\n\nSome of the type descriptions below contain a paragraph listing\n\'special attributes.\' These are attributes that provide access to the\nimplementation and are not intended for general use. Their definition\nmay change in the future.\n\nNone\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name ``None``.\n It is used to signify the absence of a value in many situations,\n e.g., it is returned from functions that don\'t explicitly return\n anything. Its truth value is false.\n\nNotImplemented\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n ``NotImplemented``. Numeric methods and rich comparison methods may\n return this value if they do not implement the operation for the\n operands provided. (The interpreter will then try the reflected\n operation, or some other fallback, depending on the operator.) Its\n truth value is true.\n\nEllipsis\n This type has a single value. There is a single object with this\n value. This object is accessed through the built-in name\n ``Ellipsis``. It is used to indicate the presence of the ``...``\n syntax in a slice. Its truth value is true.\n\n``numbers.Number``\n These are created by numeric literals and returned as results by\n arithmetic operators and arithmetic built-in functions. Numeric\n objects are immutable; once created their value never changes.\n Python numbers are of course strongly related to mathematical\n numbers, but subject to the limitations of numerical representation\n in computers.\n\n Python distinguishes between integers, floating point numbers, and\n complex numbers:\n\n ``numbers.Integral``\n These represent elements from the mathematical set of integers\n (positive and negative).\n\n There are three types of integers:\n\n Plain integers\n These represent numbers in the range -2147483648 through\n 2147483647. (The range may be larger on machines with a\n larger natural word size, but not smaller.) When the result\n of an operation would fall outside this range, the result is\n normally returned as a long integer (in some cases, the\n exception ``OverflowError`` is raised instead). For the\n purpose of shift and mask operations, integers are assumed to\n have a binary, 2\'s complement notation using 32 or more bits,\n and hiding no bits from the user (i.e., all 4294967296\n different bit patterns correspond to different values).\n\n Long integers\n These represent numbers in an unlimited range, subject to\n available (virtual) memory only. For the purpose of shift\n and mask operations, a binary representation is assumed, and\n negative numbers are represented in a variant of 2\'s\n complement which gives the illusion of an infinite string of\n sign bits extending to the left.\n\n Booleans\n These represent the truth values False and True. The two\n objects representing the values ``False`` and ``True`` are\n the only Boolean objects. The Boolean type is a subtype of\n plain integers, and Boolean values behave like the values 0\n and 1, respectively, in almost all contexts, the exception\n being that when converted to a string, the strings\n ``"False"`` or ``"True"`` are returned, respectively.\n\n The rules for integer representation are intended to give the\n most meaningful interpretation of shift and mask operations\n involving negative integers and the least surprises when\n switching between the plain and long integer domains. Any\n operation, if it yields a result in the plain integer domain,\n will yield the same result in the long integer domain or when\n using mixed operands. The switch between domains is transparent\n to the programmer.\n\n ``numbers.Real`` (``float``)\n These represent machine-level double precision floating point\n numbers. You are at the mercy of the underlying machine\n architecture (and C or Java implementation) for the accepted\n range and handling of overflow. Python does not support single-\n precision floating point numbers; the savings in processor and\n memory usage that are usually the reason for using these is\n dwarfed by the overhead of using objects in Python, so there is\n no reason to complicate the language with two kinds of floating\n point numbers.\n\n ``numbers.Complex``\n These represent complex numbers as a pair of machine-level\n double precision floating point numbers. The same caveats apply\n as for floating point numbers. The real and imaginary parts of a\n complex number ``z`` can be retrieved through the read-only\n attributes ``z.real`` and ``z.imag``.\n\nSequences\n These represent finite ordered sets indexed by non-negative\n numbers. The built-in function ``len()`` returns the number of\n items of a sequence. When the length of a sequence is *n*, the\n index set contains the numbers 0, 1, ..., *n*-1. Item *i* of\n sequence *a* is selected by ``a[i]``.\n\n Sequences also support slicing: ``a[i:j]`` selects all items with\n index *k* such that *i* ``<=`` *k* ``<`` *j*. When used as an\n expression, a slice is a sequence of the same type. This implies\n that the index set is renumbered so that it starts at 0.\n\n Some sequences also support "extended slicing" with a third "step"\n parameter: ``a[i:j:k]`` selects all items of *a* with index *x*\n where ``x = i + n*k``, *n* ``>=`` ``0`` and *i* ``<=`` *x* ``<``\n *j*.\n\n Sequences are distinguished according to their mutability:\n\n Immutable sequences\n An object of an immutable sequence type cannot change once it is\n created. (If the object contains references to other objects,\n these other objects may be mutable and may be changed; however,\n the collection of objects directly referenced by an immutable\n object cannot change.)\n\n The following types are immutable sequences:\n\n Strings\n The items of a string are characters. There is no separate\n character type; a character is represented by a string of one\n item. Characters represent (at least) 8-bit bytes. The\n built-in functions ``chr()`` and ``ord()`` convert between\n characters and nonnegative integers representing the byte\n values. Bytes with the values 0-127 usually represent the\n corresponding ASCII values, but the interpretation of values\n is up to the program. The string data type is also used to\n represent arrays of bytes, e.g., to hold data read from a\n file.\n\n (On systems whose native character set is not ASCII, strings\n may use EBCDIC in their internal representation, provided the\n functions ``chr()`` and ``ord()`` implement a mapping between\n ASCII and EBCDIC, and string comparison preserves the ASCII\n order. Or perhaps someone can propose a better rule?)\n\n Unicode\n The items of a Unicode object are Unicode code units. A\n Unicode code unit is represented by a Unicode object of one\n item and can hold either a 16-bit or 32-bit value\n representing a Unicode ordinal (the maximum value for the\n ordinal is given in ``sys.maxunicode``, and depends on how\n Python is configured at compile time). Surrogate pairs may\n be present in the Unicode object, and will be reported as two\n separate items. The built-in functions ``unichr()`` and\n ``ord()`` convert between code units and nonnegative integers\n representing the Unicode ordinals as defined in the Unicode\n Standard 3.0. Conversion from and to other encodings are\n possible through the Unicode method ``encode()`` and the\n built-in function ``unicode()``.\n\n Tuples\n The items of a tuple are arbitrary Python objects. Tuples of\n two or more items are formed by comma-separated lists of\n expressions. A tuple of one item (a \'singleton\') can be\n formed by affixing a comma to an expression (an expression by\n itself does not create a tuple, since parentheses must be\n usable for grouping of expressions). An empty tuple can be\n formed by an empty pair of parentheses.\n\n Mutable sequences\n Mutable sequences can be changed after they are created. The\n subscription and slicing notations can be used as the target of\n assignment and ``del`` (delete) statements.\n\n There are currently two intrinsic mutable sequence types:\n\n Lists\n The items of a list are arbitrary Python objects. Lists are\n formed by placing a comma-separated list of expressions in\n square brackets. (Note that there are no special cases needed\n to form lists of length 0 or 1.)\n\n Byte Arrays\n A bytearray object is a mutable array. They are created by\n the built-in ``bytearray()`` constructor. Aside from being\n mutable (and hence unhashable), byte arrays otherwise provide\n the same interface and functionality as immutable bytes\n objects.\n\n The extension module ``array`` provides an additional example of\n a mutable sequence type.\n\nSet types\n These represent unordered, finite sets of unique, immutable\n objects. As such, they cannot be indexed by any subscript. However,\n they can be iterated over, and the built-in function ``len()``\n returns the number of items in a set. Common uses for sets are fast\n membership testing, removing duplicates from a sequence, and\n computing mathematical operations such as intersection, union,\n difference, and symmetric difference.\n\n For set elements, the same immutability rules apply as for\n dictionary keys. Note that numeric types obey the normal rules for\n numeric comparison: if two numbers compare equal (e.g., ``1`` and\n ``1.0``), only one of them can be contained in a set.\n\n There are currently two intrinsic set types:\n\n Sets\n These represent a mutable set. They are created by the built-in\n ``set()`` constructor and can be modified afterwards by several\n methods, such as ``add()``.\n\n Frozen sets\n These represent an immutable set. They are created by the\n built-in ``frozenset()`` constructor. As a frozenset is\n immutable and *hashable*, it can be used again as an element of\n another set, or as a dictionary key.\n\nMappings\n These represent finite sets of objects indexed by arbitrary index\n sets. The subscript notation ``a[k]`` selects the item indexed by\n ``k`` from the mapping ``a``; this can be used in expressions and\n as the target of assignments or ``del`` statements. The built-in\n function ``len()`` returns the number of items in a mapping.\n\n There is currently a single intrinsic mapping type:\n\n Dictionaries\n These represent finite sets of objects indexed by nearly\n arbitrary values. The only types of values not acceptable as\n keys are values containing lists or dictionaries or other\n mutable types that are compared by value rather than by object\n identity, the reason being that the efficient implementation of\n dictionaries requires a key\'s hash value to remain constant.\n Numeric types used for keys obey the normal rules for numeric\n comparison: if two numbers compare equal (e.g., ``1`` and\n ``1.0``) then they can be used interchangeably to index the same\n dictionary entry.\n\n Dictionaries are mutable; they can be created by the ``{...}``\n notation (see section *Dictionary displays*).\n\n The extension modules ``dbm``, ``gdbm``, and ``bsddb`` provide\n additional examples of mapping types.\n\nCallable types\n These are the types to which the function call operation (see\n section *Calls*) can be applied:\n\n User-defined functions\n A user-defined function object is created by a function\n definition (see section *Function definitions*). It should be\n called with an argument list containing the same number of items\n as the function\'s formal parameter list.\n\n Special attributes:\n\n +-------------------------+---------------------------------+-------------+\n | Attribute | Meaning | |\n +=========================+=================================+=============+\n | ``__doc__`` | The function\'s documentation | Writable |\n | ``func_doc`` | string, or ``None`` if | |\n | | unavailable. | |\n +-------------------------+---------------------------------+-------------+\n | ``__name__`` | The function\'s name. | Writable |\n | ``func_name`` | | |\n +-------------------------+---------------------------------+-------------+\n | ``__module__`` | The name of the module the | Writable |\n | | function was defined in, or | |\n | | ``None`` if unavailable. | |\n +-------------------------+---------------------------------+-------------+\n | ``__defaults__`` | A tuple containing default | Writable |\n | ``func_defaults`` | argument values for those | |\n | | arguments that have defaults, | |\n | | or ``None`` if no arguments | |\n | | have a default value. | |\n +-------------------------+---------------------------------+-------------+\n | ``__code__`` | The code object representing | Writable |\n | ``func_code`` | the compiled function body. | |\n +-------------------------+---------------------------------+-------------+\n | ``__globals__`` | A reference to the dictionary | Read-only |\n | ``func_globals`` | that holds the function\'s | |\n | | global variables --- the global | |\n | | namespace of the module in | |\n | | which the function was defined. | |\n +-------------------------+---------------------------------+-------------+\n | ``__dict__`` | The namespace supporting | Writable |\n | ``func_dict`` | arbitrary function attributes. | |\n +-------------------------+---------------------------------+-------------+\n | ``__closure__`` | ``None`` or a tuple of cells | Read-only |\n | ``func_closure`` | that contain bindings for the | |\n | | function\'s free variables. | |\n +-------------------------+---------------------------------+-------------+\n\n Most of the attributes labelled "Writable" check the type of the\n assigned value.\n\n Changed in version 2.4: ``func_name`` is now writable.\n\n Changed in version 2.6: The double-underscore attributes\n ``__closure__``, ``__code__``, ``__defaults__``, and\n ``__globals__`` were introduced as aliases for the corresponding\n ``func_*`` attributes for forwards compatibility with Python 3.\n\n Function objects also support getting and setting arbitrary\n attributes, which can be used, for example, to attach metadata\n to functions. Regular attribute dot-notation is used to get and\n set such attributes. *Note that the current implementation only\n supports function attributes on user-defined functions. Function\n attributes on built-in functions may be supported in the\n future.*\n\n Additional information about a function\'s definition can be\n retrieved from its code object; see the description of internal\n types below.\n\n User-defined methods\n A user-defined method object combines a class, a class instance\n (or ``None``) and any callable object (normally a user-defined\n function).\n\n Special read-only attributes: ``im_self`` is the class instance\n object, ``im_func`` is the function object; ``im_class`` is the\n class of ``im_self`` for bound methods or the class that asked\n for the method for unbound methods; ``__doc__`` is the method\'s\n documentation (same as ``im_func.__doc__``); ``__name__`` is the\n method name (same as ``im_func.__name__``); ``__module__`` is\n the name of the module the method was defined in, or ``None`` if\n unavailable.\n\n Changed in version 2.2: ``im_self`` used to refer to the class\n that defined the method.\n\n Changed in version 2.6: For Python 3 forward-compatibility,\n ``im_func`` is also available as ``__func__``, and ``im_self``\n as ``__self__``.\n\n Methods also support accessing (but not setting) the arbitrary\n function attributes on the underlying function object.\n\n User-defined method objects may be created when getting an\n attribute of a class (perhaps via an instance of that class), if\n that attribute is a user-defined function object, an unbound\n user-defined method object, or a class method object. When the\n attribute is a user-defined method object, a new method object\n is only created if the class from which it is being retrieved is\n the same as, or a derived class of, the class stored in the\n original method object; otherwise, the original method object is\n used as it is.\n\n When a user-defined method object is created by retrieving a\n user-defined function object from a class, its ``im_self``\n attribute is ``None`` and the method object is said to be\n unbound. When one is created by retrieving a user-defined\n function object from a class via one of its instances, its\n ``im_self`` attribute is the instance, and the method object is\n said to be bound. In either case, the new method\'s ``im_class``\n attribute is the class from which the retrieval takes place, and\n its ``im_func`` attribute is the original function object.\n\n When a user-defined method object is created by retrieving\n another method object from a class or instance, the behaviour is\n the same as for a function object, except that the ``im_func``\n attribute of the new instance is not the original method object\n but its ``im_func`` attribute.\n\n When a user-defined method object is created by retrieving a\n class method object from a class or instance, its ``im_self``\n attribute is the class itself, and its ``im_func`` attribute is\n the function object underlying the class method.\n\n When an unbound user-defined method object is called, the\n underlying function (``im_func``) is called, with the\n restriction that the first argument must be an instance of the\n proper class (``im_class``) or of a derived class thereof.\n\n When a bound user-defined method object is called, the\n underlying function (``im_func``) is called, inserting the class\n instance (``im_self``) in front of the argument list. For\n instance, when ``C`` is a class which contains a definition for\n a function ``f()``, and ``x`` is an instance of ``C``, calling\n ``x.f(1)`` is equivalent to calling ``C.f(x, 1)``.\n\n When a user-defined method object is derived from a class method\n object, the "class instance" stored in ``im_self`` will actually\n be the class itself, so that calling either ``x.f(1)`` or\n ``C.f(1)`` is equivalent to calling ``f(C,1)`` where ``f`` is\n the underlying function.\n\n Note that the transformation from function object to (unbound or\n bound) method object happens each time the attribute is\n retrieved from the class or instance. In some cases, a fruitful\n optimization is to assign the attribute to a local variable and\n call that local variable. Also notice that this transformation\n only happens for user-defined functions; other callable objects\n (and all non-callable objects) are retrieved without\n transformation. It is also important to note that user-defined\n functions which are attributes of a class instance are not\n converted to bound methods; this *only* happens when the\n function is an attribute of the class.\n\n Generator functions\n A function or method which uses the ``yield`` statement (see\n section *The yield statement*) is called a *generator function*.\n Such a function, when called, always returns an iterator object\n which can be used to execute the body of the function: calling\n the iterator\'s ``next()`` method will cause the function to\n execute until it provides a value using the ``yield`` statement.\n When the function executes a ``return`` statement or falls off\n the end, a ``StopIteration`` exception is raised and the\n iterator will have reached the end of the set of values to be\n returned.\n\n Built-in functions\n A built-in function object is a wrapper around a C function.\n Examples of built-in functions are ``len()`` and ``math.sin()``\n (``math`` is a standard built-in module). The number and type of\n the arguments are determined by the C function. Special read-\n only attributes: ``__doc__`` is the function\'s documentation\n string, or ``None`` if unavailable; ``__name__`` is the\n function\'s name; ``__self__`` is set to ``None`` (but see the\n next item); ``__module__`` is the name of the module the\n function was defined in or ``None`` if unavailable.\n\n Built-in methods\n This is really a different disguise of a built-in function, this\n time containing an object passed to the C function as an\n implicit extra argument. An example of a built-in method is\n ``alist.append()``, assuming *alist* is a list object. In this\n case, the special read-only attribute ``__self__`` is set to the\n object denoted by *alist*.\n\n Class Types\n Class types, or "new-style classes," are callable. These\n objects normally act as factories for new instances of\n themselves, but variations are possible for class types that\n override ``__new__()``. The arguments of the call are passed to\n ``__new__()`` and, in the typical case, to ``__init__()`` to\n initialize the new instance.\n\n Classic Classes\n Class objects are described below. When a class object is\n called, a new class instance (also described below) is created\n and returned. This implies a call to the class\'s ``__init__()``\n method if it has one. Any arguments are passed on to the\n ``__init__()`` method. If there is no ``__init__()`` method,\n the class must be called without arguments.\n\n Class instances\n Class instances are described below. Class instances are\n callable only when the class has a ``__call__()`` method;\n ``x(arguments)`` is a shorthand for ``x.__call__(arguments)``.\n\nModules\n Modules are imported by the ``import`` statement (see section *The\n import statement*). A module object has a namespace implemented by\n a dictionary object (this is the dictionary referenced by the\n func_globals attribute of functions defined in the module).\n Attribute references are translated to lookups in this dictionary,\n e.g., ``m.x`` is equivalent to ``m.__dict__["x"]``. A module object\n does not contain the code object used to initialize the module\n (since it isn\'t needed once the initialization is done).\n\n Attribute assignment updates the module\'s namespace dictionary,\n e.g., ``m.x = 1`` is equivalent to ``m.__dict__["x"] = 1``.\n\n Special read-only attribute: ``__dict__`` is the module\'s namespace\n as a dictionary object.\n\n **CPython implementation detail:** Because of the way CPython\n clears module dictionaries, the module dictionary will be cleared\n when the module falls out of scope even if the dictionary still has\n live references. To avoid this, copy the dictionary or keep the\n module around while using its dictionary directly.\n\n Predefined (writable) attributes: ``__name__`` is the module\'s\n name; ``__doc__`` is the module\'s documentation string, or ``None``\n if unavailable; ``__file__`` is the pathname of the file from which\n the module was loaded, if it was loaded from a file. The\n ``__file__`` attribute is not present for C modules that are\n statically linked into the interpreter; for extension modules\n loaded dynamically from a shared library, it is the pathname of the\n shared library file.\n\nClasses\n Both class types (new-style classes) and class objects (old-\n style/classic classes) are typically created by class definitions\n (see section *Class definitions*). A class has a namespace\n implemented by a dictionary object. Class attribute references are\n translated to lookups in this dictionary, e.g., ``C.x`` is\n translated to ``C.__dict__["x"]`` (although for new-style classes\n in particular there are a number of hooks which allow for other\n means of locating attributes). When the attribute name is not found\n there, the attribute search continues in the base classes. For\n old-style classes, the search is depth-first, left-to-right in the\n order of occurrence in the base class list. New-style classes use\n the more complex C3 method resolution order which behaves correctly\n even in the presence of \'diamond\' inheritance structures where\n there are multiple inheritance paths leading back to a common\n ancestor. Additional details on the C3 MRO used by new-style\n classes can be found in the documentation accompanying the 2.3\n release at http://www.python.org/download/releases/2.3/mro/.\n\n When a class attribute reference (for class ``C``, say) would yield\n a user-defined function object or an unbound user-defined method\n object whose associated class is either ``C`` or one of its base\n classes, it is transformed into an unbound user-defined method\n object whose ``im_class`` attribute is ``C``. When it would yield a\n class method object, it is transformed into a bound user-defined\n method object whose ``im_self`` attribute is ``C``. When it would\n yield a static method object, it is transformed into the object\n wrapped by the static method object. See section *Implementing\n Descriptors* for another way in which attributes retrieved from a\n class may differ from those actually contained in its ``__dict__``\n (note that only new-style classes support descriptors).\n\n Class attribute assignments update the class\'s dictionary, never\n the dictionary of a base class.\n\n A class object can be called (see above) to yield a class instance\n (see below).\n\n Special attributes: ``__name__`` is the class name; ``__module__``\n is the module name in which the class was defined; ``__dict__`` is\n the dictionary containing the class\'s namespace; ``__bases__`` is a\n tuple (possibly empty or a singleton) containing the base classes,\n in the order of their occurrence in the base class list;\n ``__doc__`` is the class\'s documentation string, or None if\n undefined.\n\nClass instances\n A class instance is created by calling a class object (see above).\n A class instance has a namespace implemented as a dictionary which\n is the first place in which attribute references are searched.\n When an attribute is not found there, and the instance\'s class has\n an attribute by that name, the search continues with the class\n attributes. If a class attribute is found that is a user-defined\n function object or an unbound user-defined method object whose\n associated class is the class (call it ``C``) of the instance for\n which the attribute reference was initiated or one of its bases, it\n is transformed into a bound user-defined method object whose\n ``im_class`` attribute is ``C`` and whose ``im_self`` attribute is\n the instance. Static method and class method objects are also\n transformed, as if they had been retrieved from class ``C``; see\n above under "Classes". See section *Implementing Descriptors* for\n another way in which attributes of a class retrieved via its\n instances may differ from the objects actually stored in the\n class\'s ``__dict__``. If no class attribute is found, and the\n object\'s class has a ``__getattr__()`` method, that is called to\n satisfy the lookup.\n\n Attribute assignments and deletions update the instance\'s\n dictionary, never a class\'s dictionary. If the class has a\n ``__setattr__()`` or ``__delattr__()`` method, this is called\n instead of updating the instance dictionary directly.\n\n Class instances can pretend to be numbers, sequences, or mappings\n if they have methods with certain special names. See section\n *Special method names*.\n\n Special attributes: ``__dict__`` is the attribute dictionary;\n ``__class__`` is the instance\'s class.\n\nFiles\n A file object represents an open file. File objects are created by\n the ``open()`` built-in function, and also by ``os.popen()``,\n ``os.fdopen()``, and the ``makefile()`` method of socket objects\n (and perhaps by other functions or methods provided by extension\n modules). The objects ``sys.stdin``, ``sys.stdout`` and\n ``sys.stderr`` are initialized to file objects corresponding to the\n interpreter\'s standard input, output and error streams. See *File\n Objects* for complete documentation of file objects.\n\nInternal types\n A few types used internally by the interpreter are exposed to the\n user. Their definitions may change with future versions of the\n interpreter, but they are mentioned here for completeness.\n\n Code objects\n Code objects represent *byte-compiled* executable Python code,\n or *bytecode*. The difference between a code object and a\n function object is that the function object contains an explicit\n reference to the function\'s globals (the module in which it was\n defined), while a code object contains no context; also the\n default argument values are stored in the function object, not\n in the code object (because they represent values calculated at\n run-time). Unlike function objects, code objects are immutable\n and contain no references (directly or indirectly) to mutable\n objects.\n\n Special read-only attributes: ``co_name`` gives the function\n name; ``co_argcount`` is the number of positional arguments\n (including arguments with default values); ``co_nlocals`` is the\n number of local variables used by the function (including\n arguments); ``co_varnames`` is a tuple containing the names of\n the local variables (starting with the argument names);\n ``co_cellvars`` is a tuple containing the names of local\n variables that are referenced by nested functions;\n ``co_freevars`` is a tuple containing the names of free\n variables; ``co_code`` is a string representing the sequence of\n bytecode instructions; ``co_consts`` is a tuple containing the\n literals used by the bytecode; ``co_names`` is a tuple\n containing the names used by the bytecode; ``co_filename`` is\n the filename from which the code was compiled;\n ``co_firstlineno`` is the first line number of the function;\n ``co_lnotab`` is a string encoding the mapping from bytecode\n offsets to line numbers (for details see the source code of the\n interpreter); ``co_stacksize`` is the required stack size\n (including local variables); ``co_flags`` is an integer encoding\n a number of flags for the interpreter.\n\n The following flag bits are defined for ``co_flags``: bit\n ``0x04`` is set if the function uses the ``*arguments`` syntax\n to accept an arbitrary number of positional arguments; bit\n ``0x08`` is set if the function uses the ``**keywords`` syntax\n to accept arbitrary keyword arguments; bit ``0x20`` is set if\n the function is a generator.\n\n Future feature declarations (``from __future__ import\n division``) also use bits in ``co_flags`` to indicate whether a\n code object was compiled with a particular feature enabled: bit\n ``0x2000`` is set if the function was compiled with future\n division enabled; bits ``0x10`` and ``0x1000`` were used in\n earlier versions of Python.\n\n Other bits in ``co_flags`` are reserved for internal use.\n\n If a code object represents a function, the first item in\n ``co_consts`` is the documentation string of the function, or\n ``None`` if undefined.\n\n Frame objects\n Frame objects represent execution frames. They may occur in\n traceback objects (see below).\n\n Special read-only attributes: ``f_back`` is to the previous\n stack frame (towards the caller), or ``None`` if this is the\n bottom stack frame; ``f_code`` is the code object being executed\n in this frame; ``f_locals`` is the dictionary used to look up\n local variables; ``f_globals`` is used for global variables;\n ``f_builtins`` is used for built-in (intrinsic) names;\n ``f_restricted`` is a flag indicating whether the function is\n executing in restricted execution mode; ``f_lasti`` gives the\n precise instruction (this is an index into the bytecode string\n of the code object).\n\n Special writable attributes: ``f_trace``, if not ``None``, is a\n function called at the start of each source code line (this is\n used by the debugger); ``f_exc_type``, ``f_exc_value``,\n ``f_exc_traceback`` represent the last exception raised in the\n parent frame provided another exception was ever raised in the\n current frame (in all other cases they are None); ``f_lineno``\n is the current line number of the frame --- writing to this from\n within a trace function jumps to the given line (only for the\n bottom-most frame). A debugger can implement a Jump command\n (aka Set Next Statement) by writing to f_lineno.\n\n Traceback objects\n Traceback objects represent a stack trace of an exception. A\n traceback object is created when an exception occurs. When the\n search for an exception handler unwinds the execution stack, at\n each unwound level a traceback object is inserted in front of\n the current traceback. When an exception handler is entered,\n the stack trace is made available to the program. (See section\n *The try statement*.) It is accessible as ``sys.exc_traceback``,\n and also as the third item of the tuple returned by\n ``sys.exc_info()``. The latter is the preferred interface,\n since it works correctly when the program is using multiple\n threads. When the program contains no suitable handler, the\n stack trace is written (nicely formatted) to the standard error\n stream; if the interpreter is interactive, it is also made\n available to the user as ``sys.last_traceback``.\n\n Special read-only attributes: ``tb_next`` is the next level in\n the stack trace (towards the frame where the exception\n occurred), or ``None`` if there is no next level; ``tb_frame``\n points to the execution frame of the current level;\n ``tb_lineno`` gives the line number where the exception\n occurred; ``tb_lasti`` indicates the precise instruction. The\n line number and last instruction in the traceback may differ\n from the line number of its frame object if the exception\n occurred in a ``try`` statement with no matching except clause\n or with a finally clause.\n\n Slice objects\n Slice objects are used to represent slices when *extended slice\n syntax* is used. This is a slice using two colons, or multiple\n slices or ellipses separated by commas, e.g., ``a[i:j:step]``,\n ``a[i:j, k:l]``, or ``a[..., i:j]``. They are also created by\n the built-in ``slice()`` function.\n\n Special read-only attributes: ``start`` is the lower bound;\n ``stop`` is the upper bound; ``step`` is the step value; each is\n ``None`` if omitted. These attributes can have any type.\n\n Slice objects support one method:\n\n slice.indices(self, length)\n\n This method takes a single integer argument *length* and\n computes information about the extended slice that the slice\n object would describe if applied to a sequence of *length*\n items. It returns a tuple of three integers; respectively\n these are the *start* and *stop* indices and the *step* or\n stride length of the slice. Missing or out-of-bounds indices\n are handled in a manner consistent with regular slices.\n\n New in version 2.3.\n\n Static method objects\n Static method objects provide a way of defeating the\n transformation of function objects to method objects described\n above. A static method object is a wrapper around any other\n object, usually a user-defined method object. When a static\n method object is retrieved from a class or a class instance, the\n object actually returned is the wrapped object, which is not\n subject to any further transformation. Static method objects are\n not themselves callable, although the objects they wrap usually\n are. Static method objects are created by the built-in\n ``staticmethod()`` constructor.\n\n Class method objects\n A class method object, like a static method object, is a wrapper\n around another object that alters the way in which that object\n is retrieved from classes and class instances. The behaviour of\n class method objects upon such retrieval is described above,\n under "User-defined methods". Class method objects are created\n by the built-in ``classmethod()`` constructor.\n', 'typesfunctions': '\nFunctions\n*********\n\nFunction objects are created by function definitions. The only\noperation on a function object is to call it: ``func(argument-list)``.\n\nThere are really two flavors of function objects: built-in functions\nand user-defined functions. Both support the same operation (to call\nthe function), but the implementation is different, hence the\ndifferent object types.\n\nSee *Function definitions* for more information.\n', 'typesmapping': '\nMapping Types --- ``dict``\n**************************\n\nA *mapping* object maps *hashable* values to arbitrary objects.\nMappings are mutable objects. There is currently only one standard\nmapping type, the *dictionary*. (For other containers see the built\nin ``list``, ``set``, and ``tuple`` classes, and the ``collections``\nmodule.)\n\nA dictionary\'s keys are *almost* arbitrary values. Values that are\nnot *hashable*, that is, values containing lists, dictionaries or\nother mutable types (that are compared by value rather than by object\nidentity) may not be used as keys. Numeric types used for keys obey\nthe normal rules for numeric comparison: if two numbers compare equal\n(such as ``1`` and ``1.0``) then they can be used interchangeably to\nindex the same dictionary entry. (Note however, that since computers\nstore floating-point numbers as approximations it is usually unwise to\nuse them as dictionary keys.)\n\nDictionaries can be created by placing a comma-separated list of\n``key: value`` pairs within braces, for example: ``{\'jack\': 4098,\n\'sjoerd\': 4127}`` or ``{4098: \'jack\', 4127: \'sjoerd\'}``, or by the\n``dict`` constructor.\n\nclass class dict(**kwarg)\nclass class dict(mapping, **kwarg)\nclass class dict(iterable, **kwarg)\n\n Return a new dictionary initialized from an optional positional\n argument and a possibly empty set of keyword arguments.\n\n If no positional argument is given, an empty dictionary is created.\n If a positional argument is given and it is a mapping object, a\n dictionary is created with the same key-value pairs as the mapping\n object. Otherwise, the positional argument must be an *iterator*\n object. Each item in the iterable must itself be an iterator with\n exactly two objects. The first object of each item becomes a key\n in the new dictionary, and the second object the corresponding\n value. If a key occurs more than once, the last value for that key\n becomes the corresponding value in the new dictionary.\n\n If keyword arguments are given, the keyword arguments and their\n values are added to the dictionary created from the positional\n argument. If a key being added is already present, the value from\n the keyword argument replaces the value from the positional\n argument.\n\n To illustrate, the following examples all return a dictionary equal\n to ``{"one": 1, "two": 2, "three": 3}``:\n\n >>> a = dict(one=1, two=2, three=3)\n >>> b = {\'one\': 1, \'two\': 2, \'three\': 3}\n >>> c = dict(zip([\'one\', \'two\', \'three\'], [1, 2, 3]))\n >>> d = dict([(\'two\', 2), (\'one\', 1), (\'three\', 3)])\n >>> e = dict({\'three\': 3, \'one\': 1, \'two\': 2})\n >>> a == b == c == d == e\n True\n\n Providing keyword arguments as in the first example only works for\n keys that are valid Python identifiers. Otherwise, any valid keys\n can be used.\n\n New in version 2.2.\n\n Changed in version 2.3: Support for building a dictionary from\n keyword arguments added.\n\n These are the operations that dictionaries support (and therefore,\n custom mapping types should support too):\n\n len(d)\n\n Return the number of items in the dictionary *d*.\n\n d[key]\n\n Return the item of *d* with key *key*. Raises a ``KeyError`` if\n *key* is not in the map.\n\n New in version 2.5: If a subclass of dict defines a method\n ``__missing__()``, if the key *key* is not present, the\n ``d[key]`` operation calls that method with the key *key* as\n argument. The ``d[key]`` operation then returns or raises\n whatever is returned or raised by the ``__missing__(key)`` call\n if the key is not present. No other operations or methods invoke\n ``__missing__()``. If ``__missing__()`` is not defined,\n ``KeyError`` is raised. ``__missing__()`` must be a method; it\n cannot be an instance variable. For an example, see\n ``collections.defaultdict``.\n\n d[key] = value\n\n Set ``d[key]`` to *value*.\n\n del d[key]\n\n Remove ``d[key]`` from *d*. Raises a ``KeyError`` if *key* is\n not in the map.\n\n key in d\n\n Return ``True`` if *d* has a key *key*, else ``False``.\n\n New in version 2.2.\n\n key not in d\n\n Equivalent to ``not key in d``.\n\n New in version 2.2.\n\n iter(d)\n\n Return an iterator over the keys of the dictionary. This is a\n shortcut for ``iterkeys()``.\n\n clear()\n\n Remove all items from the dictionary.\n\n copy()\n\n Return a shallow copy of the dictionary.\n\n fromkeys(seq[, value])\n\n Create a new dictionary with keys from *seq* and values set to\n *value*.\n\n ``fromkeys()`` is a class method that returns a new dictionary.\n *value* defaults to ``None``.\n\n New in version 2.3.\n\n get(key[, default])\n\n Return the value for *key* if *key* is in the dictionary, else\n *default*. If *default* is not given, it defaults to ``None``,\n so that this method never raises a ``KeyError``.\n\n has_key(key)\n\n Test for the presence of *key* in the dictionary. ``has_key()``\n is deprecated in favor of ``key in d``.\n\n items()\n\n Return a copy of the dictionary\'s list of ``(key, value)``\n pairs.\n\n **CPython implementation detail:** Keys and values are listed in\n an arbitrary order which is non-random, varies across Python\n implementations, and depends on the dictionary\'s history of\n insertions and deletions.\n\n If ``items()``, ``keys()``, ``values()``, ``iteritems()``,\n ``iterkeys()``, and ``itervalues()`` are called with no\n intervening modifications to the dictionary, the lists will\n directly correspond. This allows the creation of ``(value,\n key)`` pairs using ``zip()``: ``pairs = zip(d.values(),\n d.keys())``. The same relationship holds for the ``iterkeys()``\n and ``itervalues()`` methods: ``pairs = zip(d.itervalues(),\n d.iterkeys())`` provides the same value for ``pairs``. Another\n way to create the same list is ``pairs = [(v, k) for (k, v) in\n d.iteritems()]``.\n\n iteritems()\n\n Return an iterator over the dictionary\'s ``(key, value)`` pairs.\n See the note for ``dict.items()``.\n\n Using ``iteritems()`` while adding or deleting entries in the\n dictionary may raise a ``RuntimeError`` or fail to iterate over\n all entries.\n\n New in version 2.2.\n\n iterkeys()\n\n Return an iterator over the dictionary\'s keys. See the note for\n ``dict.items()``.\n\n Using ``iterkeys()`` while adding or deleting entries in the\n dictionary may raise a ``RuntimeError`` or fail to iterate over\n all entries.\n\n New in version 2.2.\n\n itervalues()\n\n Return an iterator over the dictionary\'s values. See the note\n for ``dict.items()``.\n\n Using ``itervalues()`` while adding or deleting entries in the\n dictionary may raise a ``RuntimeError`` or fail to iterate over\n all entries.\n\n New in version 2.2.\n\n keys()\n\n Return a copy of the dictionary\'s list of keys. See the note\n for ``dict.items()``.\n\n pop(key[, default])\n\n If *key* is in the dictionary, remove it and return its value,\n else return *default*. If *default* is not given and *key* is\n not in the dictionary, a ``KeyError`` is raised.\n\n New in version 2.3.\n\n popitem()\n\n Remove and return an arbitrary ``(key, value)`` pair from the\n dictionary.\n\n ``popitem()`` is useful to destructively iterate over a\n dictionary, as often used in set algorithms. If the dictionary\n is empty, calling ``popitem()`` raises a ``KeyError``.\n\n setdefault(key[, default])\n\n If *key* is in the dictionary, return its value. If not, insert\n *key* with a value of *default* and return *default*. *default*\n defaults to ``None``.\n\n update([other])\n\n Update the dictionary with the key/value pairs from *other*,\n overwriting existing keys. Return ``None``.\n\n ``update()`` accepts either another dictionary object or an\n iterable of key/value pairs (as tuples or other iterables of\n length two). If keyword arguments are specified, the dictionary\n is then updated with those key/value pairs: ``d.update(red=1,\n blue=2)``.\n\n Changed in version 2.4: Allowed the argument to be an iterable\n of key/value pairs and allowed keyword arguments.\n\n values()\n\n Return a copy of the dictionary\'s list of values. See the note\n for ``dict.items()``.\n\n viewitems()\n\n Return a new view of the dictionary\'s items (``(key, value)``\n pairs). See below for documentation of view objects.\n\n New in version 2.7.\n\n viewkeys()\n\n Return a new view of the dictionary\'s keys. See below for\n documentation of view objects.\n\n New in version 2.7.\n\n viewvalues()\n\n Return a new view of the dictionary\'s values. See below for\n documentation of view objects.\n\n New in version 2.7.\n\n\nDictionary view objects\n=======================\n\nThe objects returned by ``dict.viewkeys()``, ``dict.viewvalues()`` and\n``dict.viewitems()`` are *view objects*. They provide a dynamic view\non the dictionary\'s entries, which means that when the dictionary\nchanges, the view reflects these changes.\n\nDictionary views can be iterated over to yield their respective data,\nand support membership tests:\n\nlen(dictview)\n\n Return the number of entries in the dictionary.\n\niter(dictview)\n\n Return an iterator over the keys, values or items (represented as\n tuples of ``(key, value)``) in the dictionary.\n\n Keys and values are iterated over in an arbitrary order which is\n non-random, varies across Python implementations, and depends on\n the dictionary\'s history of insertions and deletions. If keys,\n values and items views are iterated over with no intervening\n modifications to the dictionary, the order of items will directly\n correspond. This allows the creation of ``(value, key)`` pairs\n using ``zip()``: ``pairs = zip(d.values(), d.keys())``. Another\n way to create the same list is ``pairs = [(v, k) for (k, v) in\n d.items()]``.\n\n Iterating views while adding or deleting entries in the dictionary\n may raise a ``RuntimeError`` or fail to iterate over all entries.\n\nx in dictview\n\n Return ``True`` if *x* is in the underlying dictionary\'s keys,\n values or items (in the latter case, *x* should be a ``(key,\n value)`` tuple).\n\nKeys views are set-like since their entries are unique and hashable.\nIf all values are hashable, so that (key, value) pairs are unique and\nhashable, then the items view is also set-like. (Values views are not\ntreated as set-like since the entries are generally not unique.) Then\nthese set operations are available ("other" refers either to another\nview or a set):\n\ndictview & other\n\n Return the intersection of the dictview and the other object as a\n new set.\n\ndictview | other\n\n Return the union of the dictview and the other object as a new set.\n\ndictview - other\n\n Return the difference between the dictview and the other object\n (all elements in *dictview* that aren\'t in *other*) as a new set.\n\ndictview ^ other\n\n Return the symmetric difference (all elements either in *dictview*\n or *other*, but not in both) of the dictview and the other object\n as a new set.\n\nAn example of dictionary view usage:\n\n >>> dishes = {\'eggs\': 2, \'sausage\': 1, \'bacon\': 1, \'spam\': 500}\n >>> keys = dishes.viewkeys()\n >>> values = dishes.viewvalues()\n\n >>> # iteration\n >>> n = 0\n >>> for val in values:\n ... n += val\n >>> print(n)\n 504\n\n >>> # keys and values are iterated over in the same order\n >>> list(keys)\n [\'eggs\', \'bacon\', \'sausage\', \'spam\']\n >>> list(values)\n [2, 1, 1, 500]\n\n >>> # view objects are dynamic and reflect dict changes\n >>> del dishes[\'eggs\']\n >>> del dishes[\'sausage\']\n >>> list(keys)\n [\'spam\', \'bacon\']\n\n >>> # set operations\n >>> keys & {\'eggs\', \'bacon\', \'salad\'}\n {\'bacon\'}\n', 'typesmethods': '\nMethods\n*******\n\nMethods are functions that are called using the attribute notation.\nThere are two flavors: built-in methods (such as ``append()`` on\nlists) and class instance methods. Built-in methods are described\nwith the types that support them.\n\nThe implementation adds two special read-only attributes to class\ninstance methods: ``m.im_self`` is the object on which the method\noperates, and ``m.im_func`` is the function implementing the method.\nCalling ``m(arg-1, arg-2, ..., arg-n)`` is completely equivalent to\ncalling ``m.im_func(m.im_self, arg-1, arg-2, ..., arg-n)``.\n\nClass instance methods are either *bound* or *unbound*, referring to\nwhether the method was accessed through an instance or a class,\nrespectively. When a method is unbound, its ``im_self`` attribute\nwill be ``None`` and if called, an explicit ``self`` object must be\npassed as the first argument. In this case, ``self`` must be an\ninstance of the unbound method\'s class (or a subclass of that class),\notherwise a ``TypeError`` is raised.\n\nLike function objects, methods objects support getting arbitrary\nattributes. However, since method attributes are actually stored on\nthe underlying function object (``meth.im_func``), setting method\nattributes on either bound or unbound methods is disallowed.\nAttempting to set an attribute on a method results in an\n``AttributeError`` being raised. In order to set a method attribute,\nyou need to explicitly set it on the underlying function object:\n\n >>> class C:\n ... def method(self):\n ... pass\n ...\n >>> c = C()\n >>> c.method.whoami = \'my name is method\' # can\'t set on the method\n Traceback (most recent call last):\n File "", line 1, in \n AttributeError: \'instancemethod\' object has no attribute \'whoami\'\n >>> c.method.im_func.whoami = \'my name is method\'\n >>> c.method.whoami\n \'my name is method\'\n\nSee *The standard type hierarchy* for more information.\n', 'typesmodules': "\nModules\n*******\n\nThe only special operation on a module is attribute access:\n``m.name``, where *m* is a module and *name* accesses a name defined\nin *m*'s symbol table. Module attributes can be assigned to. (Note\nthat the ``import`` statement is not, strictly speaking, an operation\non a module object; ``import foo`` does not require a module object\nnamed *foo* to exist, rather it requires an (external) *definition*\nfor a module named *foo* somewhere.)\n\nA special attribute of every module is ``__dict__``. This is the\ndictionary containing the module's symbol table. Modifying this\ndictionary will actually change the module's symbol table, but direct\nassignment to the ``__dict__`` attribute is not possible (you can\nwrite ``m.__dict__['a'] = 1``, which defines ``m.a`` to be ``1``, but\nyou can't write ``m.__dict__ = {}``). Modifying ``__dict__`` directly\nis not recommended.\n\nModules built into the interpreter are written like this: ````. If loaded from a file, they are written as\n````.\n", - 'typesseq': '\nSequence Types --- ``str``, ``unicode``, ``list``, ``tuple``, ``bytearray``, ``buffer``, ``xrange``\n***************************************************************************************************\n\nThere are seven sequence types: strings, Unicode strings, lists,\ntuples, bytearrays, buffers, and xrange objects.\n\nFor other containers see the built in ``dict`` and ``set`` classes,\nand the ``collections`` module.\n\nString literals are written in single or double quotes: ``\'xyzzy\'``,\n``"frobozz"``. See *String literals* for more about string literals.\nUnicode strings are much like strings, but are specified in the syntax\nusing a preceding ``\'u\'`` character: ``u\'abc\'``, ``u"def"``. In\naddition to the functionality described here, there are also string-\nspecific methods described in the *String Methods* section. Lists are\nconstructed with square brackets, separating items with commas: ``[a,\nb, c]``. Tuples are constructed by the comma operator (not within\nsquare brackets), with or without enclosing parentheses, but an empty\ntuple must have the enclosing parentheses, such as ``a, b, c`` or\n``()``. A single item tuple must have a trailing comma, such as\n``(d,)``.\n\nBytearray objects are created with the built-in function\n``bytearray()``.\n\nBuffer objects are not directly supported by Python syntax, but can be\ncreated by calling the built-in function ``buffer()``. They don\'t\nsupport concatenation or repetition.\n\nObjects of type xrange are similar to buffers in that there is no\nspecific syntax to create them, but they are created using the\n``xrange()`` function. They don\'t support slicing, concatenation or\nrepetition, and using ``in``, ``not in``, ``min()`` or ``max()`` on\nthem is inefficient.\n\nMost sequence types support the following operations. The ``in`` and\n``not in`` operations have the same priorities as the comparison\noperations. The ``+`` and ``*`` operations have the same priority as\nthe corresponding numeric operations. [3] Additional methods are\nprovided for *Mutable Sequence Types*.\n\nThis table lists the sequence operations sorted in ascending priority\n(operations in the same box have the same priority). In the table,\n*s* and *t* are sequences of the same type; *n*, *i* and *j* are\nintegers:\n\n+--------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+====================+==================================+============+\n| ``x in s`` | ``True`` if an item of *s* is | (1) |\n| | equal to *x*, else ``False`` | |\n+--------------------+----------------------------------+------------+\n| ``x not in s`` | ``False`` if an item of *s* is | (1) |\n| | equal to *x*, else ``True`` | |\n+--------------------+----------------------------------+------------+\n| ``s + t`` | the concatenation of *s* and *t* | (6) |\n+--------------------+----------------------------------+------------+\n| ``s * n, n * s`` | *n* shallow copies of *s* | (2) |\n| | concatenated | |\n+--------------------+----------------------------------+------------+\n| ``s[i]`` | *i*th item of *s*, origin 0 | (3) |\n+--------------------+----------------------------------+------------+\n| ``s[i:j]`` | slice of *s* from *i* to *j* | (3)(4) |\n+--------------------+----------------------------------+------------+\n| ``s[i:j:k]`` | slice of *s* from *i* to *j* | (3)(5) |\n| | with step *k* | |\n+--------------------+----------------------------------+------------+\n| ``len(s)`` | length of *s* | |\n+--------------------+----------------------------------+------------+\n| ``min(s)`` | smallest item of *s* | |\n+--------------------+----------------------------------+------------+\n| ``max(s)`` | largest item of *s* | |\n+--------------------+----------------------------------+------------+\n| ``s.index(i)`` | index of the first occurrence of | |\n| | *i* in *s* | |\n+--------------------+----------------------------------+------------+\n| ``s.count(i)`` | total number of occurrences of | |\n| | *i* in *s* | |\n+--------------------+----------------------------------+------------+\n\nSequence types also support comparisons. In particular, tuples and\nlists are compared lexicographically by comparing corresponding\nelements. This means that to compare equal, every element must compare\nequal and the two sequences must be of the same type and have the same\nlength. (For full details see *Comparisons* in the language\nreference.)\n\nNotes:\n\n1. When *s* is a string or Unicode string object the ``in`` and ``not\n in`` operations act like a substring test. In Python versions\n before 2.3, *x* had to be a string of length 1. In Python 2.3 and\n beyond, *x* may be a string of any length.\n\n2. Values of *n* less than ``0`` are treated as ``0`` (which yields an\n empty sequence of the same type as *s*). Note also that the copies\n are shallow; nested structures are not copied. This often haunts\n new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that ``[[]]`` is a one-element list containing\n an empty list, so all three elements of ``[[]] * 3`` are (pointers\n to) this single empty list. Modifying any of the elements of\n ``lists`` modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n3. If *i* or *j* is negative, the index is relative to the end of the\n string: ``len(s) + i`` or ``len(s) + j`` is substituted. But note\n that ``-0`` is still ``0``.\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that ``i <= k < j``. If *i* or *j* is\n greater than ``len(s)``, use ``len(s)``. If *i* is omitted or\n ``None``, use ``0``. If *j* is omitted or ``None``, use\n ``len(s)``. If *i* is greater than or equal to *j*, the slice is\n empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index ``x = i + n*k`` such that ``0 <= n <\n (j-i)/k``. In other words, the indices are ``i``, ``i+k``,\n ``i+2*k``, ``i+3*k`` and so on, stopping when *j* is reached (but\n never including *j*). If *i* or *j* is greater than ``len(s)``,\n use ``len(s)``. If *i* or *j* are omitted or ``None``, they become\n "end" values (which end depends on the sign of *k*). Note, *k*\n cannot be zero. If *k* is ``None``, it is treated like ``1``.\n\n6. **CPython implementation detail:** If *s* and *t* are both strings,\n some Python implementations such as CPython can usually perform an\n in-place optimization for assignments of the form ``s = s + t`` or\n ``s += t``. When applicable, this optimization makes quadratic\n run-time much less likely. This optimization is both version and\n implementation dependent. For performance sensitive code, it is\n preferable to use the ``str.join()`` method which assures\n consistent linear concatenation performance across versions and\n implementations.\n\n Changed in version 2.4: Formerly, string concatenation never\n occurred in-place.\n\n\nString Methods\n==============\n\nBelow are listed the string methods which both 8-bit strings and\nUnicode objects support. Some of them are also available on\n``bytearray`` objects.\n\nIn addition, Python\'s strings support the sequence type methods\ndescribed in the *Sequence Types --- str, unicode, list, tuple,\nbytearray, buffer, xrange* section. To output formatted strings use\ntemplate strings or the ``%`` operator described in the *String\nFormatting Operations* section. Also, see the ``re`` module for string\nfunctions based on regular expressions.\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is a space).\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.decode([encoding[, errors]])\n\n Decodes the string using the codec registered for *encoding*.\n *encoding* defaults to the default string encoding. *errors* may\n be given to set a different error handling scheme. The default is\n ``\'strict\'``, meaning that encoding errors raise ``UnicodeError``.\n Other possible values are ``\'ignore\'``, ``\'replace\'`` and any other\n name registered via ``codecs.register_error()``, see section *Codec\n Base Classes*.\n\n New in version 2.2.\n\n Changed in version 2.3: Support for other error handling schemes\n added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.encode([encoding[, errors]])\n\n Return an encoded version of the string. Default encoding is the\n current default string encoding. *errors* may be given to set a\n different error handling scheme. The default for *errors* is\n ``\'strict\'``, meaning that encoding errors raise a\n ``UnicodeError``. Other possible values are ``\'ignore\'``,\n ``\'replace\'``, ``\'xmlcharrefreplace\'``, ``\'backslashreplace\'`` and\n any other name registered via ``codecs.register_error()``, see\n section *Codec Base Classes*. For a list of possible encodings, see\n section *Standard Encodings*.\n\n New in version 2.0.\n\n Changed in version 2.3: Support for ``\'xmlcharrefreplace\'`` and\n ``\'backslashreplace\'`` and other error handling schemes added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return ``True`` if the string ends with the specified *suffix*,\n otherwise return ``False``. *suffix* can also be a tuple of\n suffixes to look for. With optional *start*, test beginning at\n that position. With optional *end*, stop comparing at that\n position.\n\n Changed in version 2.5: Accept tuples as *suffix*.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab (``\\t``), one or more space characters are inserted in the\n result until the current column is equal to the next tab position.\n (The tab character itself is not copied.) If the character is a\n newline (``\\n``) or return (``\\r``), it is copied and the current\n column is reset to zero. Any other character is copied unchanged\n and the current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice ``s[start:end]``.\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return ``-1`` if *sub* is not found.\n\n Note: The ``find()`` method should be used only if you need to know the\n position of *sub*. To check if *sub* is a substring or not, use\n the ``in`` operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces ``{}``. Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\n This method of string formatting is the new standard in Python 3,\n and should be preferred to the ``%`` formatting described in\n *String Formatting Operations* in new code.\n\n New in version 2.6.\n\nstr.index(sub[, start[, end]])\n\n Like ``find()``, but raise ``ValueError`` when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. The separator between elements is the\n string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to ``len(s)``.\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or ``None``, the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\n New in version 2.5.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within ``s[start:end]``.\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return ``-1`` on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like ``rfind()`` but raises ``ValueError`` when the substring *sub*\n is not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to ``len(s)``.\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\n New in version 2.5.\n\nstr.rsplit([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n ``None``, any whitespace string is a separator. Except for\n splitting from the right, ``rsplit()`` behaves like ``split()``\n which is described in detail below.\n\n New in version 2.4.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or ``None``, the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.split([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most ``maxsplit+1``\n elements). If *maxsplit* is not specified or ``-1``, then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n ``\'1,,2\'.split(\',\')`` returns ``[\'1\', \'\', \'2\']``). The *sep*\n argument may consist of multiple characters (for example,\n ``\'1<>2<>3\'.split(\'<>\')`` returns ``[\'1\', \'2\', \'3\']``). Splitting\n an empty string with a specified separator returns ``[\'\']``.\n\n If *sep* is not specified or is ``None``, a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a ``None`` separator returns\n ``[]``.\n\n For example, ``\' 1 2 3 \'.split()`` returns ``[\'1\', \'2\', \'3\']``,\n and ``\' 1 2 3 \'.split(None, 1)`` returns ``[\'1\', \'2 3 \']``.\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example, ``\'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()`` returns\n ``[\'ab c\', \'\', \'de fg\', \'kl\']``, while the same call with\n ``splitlines(True)`` returns ``[\'ab c\\n\', \'\\n\', \'de fg\\r\',\n \'kl\\r\\n\']``.\n\n Unlike ``split()`` when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line.\n\nstr.startswith(prefix[, start[, end]])\n\n Return ``True`` if string starts with the *prefix*, otherwise\n return ``False``. *prefix* can also be a tuple of prefixes to look\n for. With optional *start*, test string beginning at that\n position. With optional *end*, stop comparing string at that\n position.\n\n Changed in version 2.5: Accept tuples as *prefix*.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or ``None``, the\n *chars* argument defaults to removing whitespace. The *chars*\n argument is not a prefix or suffix; rather, all combinations of its\n values are stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.translate(table[, deletechars])\n\n Return a copy of the string where all characters occurring in the\n optional argument *deletechars* are removed, and the remaining\n characters have been mapped through the given translation table,\n which must be a string of length 256.\n\n You can use the ``maketrans()`` helper function in the ``string``\n module to create a translation table. For string objects, set the\n *table* argument to ``None`` for translations that only delete\n characters:\n\n >>> \'read this short text\'.translate(None, \'aeiou\')\n \'rd ths shrt txt\'\n\n New in version 2.6: Support for a ``None`` *table* argument.\n\n For Unicode objects, the ``translate()`` method does not accept the\n optional *deletechars* argument. Instead, it returns a copy of the\n *s* where all characters have been mapped through the given\n translation table which must be a mapping of Unicode ordinals to\n Unicode ordinals, Unicode strings or ``None``. Unmapped characters\n are left untouched. Characters mapped to ``None`` are deleted.\n Note, a more flexible approach is to create a custom character\n mapping codec using the ``codecs`` module (see ``encodings.cp1251``\n for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that ``str.upper().isupper()`` might\n be ``False`` if ``s`` contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.zfill(width)\n\n Return the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to ``len(s)``.\n\n New in version 2.2.2.\n\nThe following methods are present only on unicode objects:\n\nunicode.isnumeric()\n\n Return ``True`` if there are only numeric characters in S,\n ``False`` otherwise. Numeric characters include digit characters,\n and all characters that have the Unicode numeric value property,\n e.g. U+2155, VULGAR FRACTION ONE FIFTH.\n\nunicode.isdecimal()\n\n Return ``True`` if there are only decimal characters in S,\n ``False`` otherwise. Decimal characters include digit characters,\n and all characters that can be used to form decimal-radix numbers,\n e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\n\nString Formatting Operations\n============================\n\nString and Unicode objects have one unique built-in operation: the\n``%`` operator (modulo). This is also known as the string\n*formatting* or *interpolation* operator. Given ``format % values``\n(where *format* is a string or Unicode object), ``%`` conversion\nspecifications in *format* are replaced with zero or more elements of\n*values*. The effect is similar to the using ``sprintf()`` in the C\nlanguage. If *format* is a Unicode object, or if any of the objects\nbeing converted using the ``%s`` conversion are Unicode objects, the\nresult will also be a Unicode object.\n\nIf *format* requires a single argument, *values* may be a single non-\ntuple object. [5] Otherwise, *values* must be a tuple with exactly\nthe number of items specified by the format string, or a single\nmapping object (for example, a dictionary).\n\nA conversion specifier contains two or more characters and has the\nfollowing components, which must occur in this order:\n\n1. The ``\'%\'`` character, which marks the start of the specifier.\n\n2. Mapping key (optional), consisting of a parenthesised sequence of\n characters (for example, ``(somename)``).\n\n3. Conversion flags (optional), which affect the result of some\n conversion types.\n\n4. Minimum field width (optional). If specified as an ``\'*\'``\n (asterisk), the actual width is read from the next element of the\n tuple in *values*, and the object to convert comes after the\n minimum field width and optional precision.\n\n5. Precision (optional), given as a ``\'.\'`` (dot) followed by the\n precision. If specified as ``\'*\'`` (an asterisk), the actual width\n is read from the next element of the tuple in *values*, and the\n value to convert comes after the precision.\n\n6. Length modifier (optional).\n\n7. Conversion type.\n\nWhen the right argument is a dictionary (or other mapping type), then\nthe formats in the string *must* include a parenthesised mapping key\ninto that dictionary inserted immediately after the ``\'%\'`` character.\nThe mapping key selects the value to be formatted from the mapping.\nFor example:\n\n>>> print \'%(language)s has %(number)03d quote types.\' % \\\n... {"language": "Python", "number": 2}\nPython has 002 quote types.\n\nIn this case no ``*`` specifiers may occur in a format (since they\nrequire a sequential parameter list).\n\nThe conversion flag characters are:\n\n+-----------+-----------------------------------------------------------------------+\n| Flag | Meaning |\n+===========+=======================================================================+\n| ``\'#\'`` | The value conversion will use the "alternate form" (where defined |\n| | below). |\n+-----------+-----------------------------------------------------------------------+\n| ``\'0\'`` | The conversion will be zero padded for numeric values. |\n+-----------+-----------------------------------------------------------------------+\n| ``\'-\'`` | The converted value is left adjusted (overrides the ``\'0\'`` |\n| | conversion if both are given). |\n+-----------+-----------------------------------------------------------------------+\n| ``\' \'`` | (a space) A blank should be left before a positive number (or empty |\n| | string) produced by a signed conversion. |\n+-----------+-----------------------------------------------------------------------+\n| ``\'+\'`` | A sign character (``\'+\'`` or ``\'-\'``) will precede the conversion |\n| | (overrides a "space" flag). |\n+-----------+-----------------------------------------------------------------------+\n\nA length modifier (``h``, ``l``, or ``L``) may be present, but is\nignored as it is not necessary for Python -- so e.g. ``%ld`` is\nidentical to ``%d``.\n\nThe conversion types are:\n\n+--------------+-------------------------------------------------------+---------+\n| Conversion | Meaning | Notes |\n+==============+=======================================================+=========+\n| ``\'d\'`` | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'i\'`` | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'o\'`` | Signed octal value. | (1) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'u\'`` | Obsolete type -- it is identical to ``\'d\'``. | (7) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'x\'`` | Signed hexadecimal (lowercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'X\'`` | Signed hexadecimal (uppercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'e\'`` | Floating point exponential format (lowercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'E\'`` | Floating point exponential format (uppercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'f\'`` | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'F\'`` | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'g\'`` | Floating point format. Uses lowercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'G\'`` | Floating point format. Uses uppercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'c\'`` | Single character (accepts integer or single character | |\n| | string). | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'r\'`` | String (converts any Python object using *repr()*). | (5) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'s\'`` | String (converts any Python object using ``str()``). | (6) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'%\'`` | No argument is converted, results in a ``\'%\'`` | |\n| | character in the result. | |\n+--------------+-------------------------------------------------------+---------+\n\nNotes:\n\n1. The alternate form causes a leading zero (``\'0\'``) to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n2. The alternate form causes a leading ``\'0x\'`` or ``\'0X\'`` (depending\n on whether the ``\'x\'`` or ``\'X\'`` format was used) to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n3. The alternate form causes the result to always contain a decimal\n point, even if no digits follow it.\n\n The precision determines the number of digits after the decimal\n point and defaults to 6.\n\n4. The alternate form causes the result to always contain a decimal\n point, and trailing zeroes are not removed as they would otherwise\n be.\n\n The precision determines the number of significant digits before\n and after the decimal point and defaults to 6.\n\n5. The ``%r`` conversion was added in Python 2.0.\n\n The precision determines the maximal number of characters used.\n\n6. If the object or format provided is a ``unicode`` string, the\n resulting string will also be ``unicode``.\n\n The precision determines the maximal number of characters used.\n\n7. See **PEP 237**.\n\nSince Python strings have an explicit length, ``%s`` conversions do\nnot assume that ``\'\\0\'`` is the end of the string.\n\nChanged in version 2.7: ``%f`` conversions for numbers whose absolute\nvalue is over 1e50 are no longer replaced by ``%g`` conversions.\n\nAdditional string operations are defined in standard modules\n``string`` and ``re``.\n\n\nXRange Type\n===========\n\nThe ``xrange`` type is an immutable sequence which is commonly used\nfor looping. The advantage of the ``xrange`` type is that an\n``xrange`` object will always take the same amount of memory, no\nmatter the size of the range it represents. There are no consistent\nperformance advantages.\n\nXRange objects have very little behavior: they only support indexing,\niteration, and the ``len()`` function.\n\n\nMutable Sequence Types\n======================\n\nList and ``bytearray`` objects support additional operations that\nallow in-place modification of the object. Other mutable sequence\ntypes (when added to the language) should also support these\noperations. Strings and tuples are immutable sequence types: such\nobjects cannot be modified once created. The following operations are\ndefined on mutable sequence types (where *x* is an arbitrary object):\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | same as ``s[len(s):len(s)] = | (2) |\n| | [x]`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(x)`` | same as ``s[len(s):len(s)] = x`` | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.count(x)`` | return number of *i*\'s for which | |\n| | ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.index(x[, i[, j]])`` | return smallest *k* such that | (4) |\n| | ``s[k] == x`` and ``i <= k < j`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | same as ``s[i:i] = [x]`` | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | same as ``x = s[i]; del s[i]; | (6) |\n| | return x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | same as ``del s[s.index(x)]`` | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (7) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.sort([cmp[, key[, | sort the items of *s* in place | (7)(8)(9)(10) |\n| reverse]]])`` | | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The C implementation of Python has historically accepted multiple\n parameters and implicitly joined them into a tuple; this no longer\n works in Python 2.0. Use of this misfeature has been deprecated\n since Python 1.4.\n\n3. *x* can be any iterable object.\n\n4. Raises ``ValueError`` when *x* is not found in *s*. When a negative\n index is passed as the second or third parameter to the ``index()``\n method, the list length is added, as for slice indices. If it is\n still negative, it is truncated to zero, as for slice indices.\n\n Changed in version 2.3: Previously, ``index()`` didn\'t have\n arguments for specifying start and stop positions.\n\n5. When a negative index is passed as the first parameter to the\n ``insert()`` method, the list length is added, as for slice\n indices. If it is still negative, it is truncated to zero, as for\n slice indices.\n\n Changed in version 2.3: Previously, all negative indices were\n truncated to zero.\n\n6. The ``pop()`` method is only supported by the list and array types.\n The optional argument *i* defaults to ``-1``, so that by default\n the last item is removed and returned.\n\n7. The ``sort()`` and ``reverse()`` methods modify the list in place\n for economy of space when sorting or reversing a large list. To\n remind you that they operate by side effect, they don\'t return the\n sorted or reversed list.\n\n8. The ``sort()`` method takes optional arguments for controlling the\n comparisons.\n\n *cmp* specifies a custom comparison function of two arguments (list\n items) which should return a negative, zero or positive number\n depending on whether the first argument is considered smaller than,\n equal to, or larger than the second argument: ``cmp=lambda x,y:\n cmp(x.lower(), y.lower())``. The default value is ``None``.\n\n *key* specifies a function of one argument that is used to extract\n a comparison key from each list element: ``key=str.lower``. The\n default value is ``None``.\n\n *reverse* is a boolean value. If set to ``True``, then the list\n elements are sorted as if each comparison were reversed.\n\n In general, the *key* and *reverse* conversion processes are much\n faster than specifying an equivalent *cmp* function. This is\n because *cmp* is called multiple times for each list element while\n *key* and *reverse* touch each element only once. Use\n ``functools.cmp_to_key()`` to convert an old-style *cmp* function\n to a *key* function.\n\n Changed in version 2.3: Support for ``None`` as an equivalent to\n omitting *cmp* was added.\n\n Changed in version 2.4: Support for *key* and *reverse* was added.\n\n9. Starting with Python 2.3, the ``sort()`` method is guaranteed to be\n stable. A sort is stable if it guarantees not to change the\n relative order of elements that compare equal --- this is helpful\n for sorting in multiple passes (for example, sort by department,\n then by salary grade).\n\n10. **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python 2.3 and newer makes the\n list appear empty for the duration, and raises ``ValueError`` if\n it can detect that the list has been mutated during a sort.\n', - 'typesseq-mutable': "\nMutable Sequence Types\n**********************\n\nList and ``bytearray`` objects support additional operations that\nallow in-place modification of the object. Other mutable sequence\ntypes (when added to the language) should also support these\noperations. Strings and tuples are immutable sequence types: such\nobjects cannot be modified once created. The following operations are\ndefined on mutable sequence types (where *x* is an arbitrary object):\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | same as ``s[len(s):len(s)] = | (2) |\n| | [x]`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(x)`` | same as ``s[len(s):len(s)] = x`` | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.count(x)`` | return number of *i*'s for which | |\n| | ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.index(x[, i[, j]])`` | return smallest *k* such that | (4) |\n| | ``s[k] == x`` and ``i <= k < j`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | same as ``s[i:i] = [x]`` | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | same as ``x = s[i]; del s[i]; | (6) |\n| | return x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | same as ``del s[s.index(x)]`` | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (7) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.sort([cmp[, key[, | sort the items of *s* in place | (7)(8)(9)(10) |\n| reverse]]])`` | | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The C implementation of Python has historically accepted multiple\n parameters and implicitly joined them into a tuple; this no longer\n works in Python 2.0. Use of this misfeature has been deprecated\n since Python 1.4.\n\n3. *x* can be any iterable object.\n\n4. Raises ``ValueError`` when *x* is not found in *s*. When a negative\n index is passed as the second or third parameter to the ``index()``\n method, the list length is added, as for slice indices. If it is\n still negative, it is truncated to zero, as for slice indices.\n\n Changed in version 2.3: Previously, ``index()`` didn't have\n arguments for specifying start and stop positions.\n\n5. When a negative index is passed as the first parameter to the\n ``insert()`` method, the list length is added, as for slice\n indices. If it is still negative, it is truncated to zero, as for\n slice indices.\n\n Changed in version 2.3: Previously, all negative indices were\n truncated to zero.\n\n6. The ``pop()`` method is only supported by the list and array types.\n The optional argument *i* defaults to ``-1``, so that by default\n the last item is removed and returned.\n\n7. The ``sort()`` and ``reverse()`` methods modify the list in place\n for economy of space when sorting or reversing a large list. To\n remind you that they operate by side effect, they don't return the\n sorted or reversed list.\n\n8. The ``sort()`` method takes optional arguments for controlling the\n comparisons.\n\n *cmp* specifies a custom comparison function of two arguments (list\n items) which should return a negative, zero or positive number\n depending on whether the first argument is considered smaller than,\n equal to, or larger than the second argument: ``cmp=lambda x,y:\n cmp(x.lower(), y.lower())``. The default value is ``None``.\n\n *key* specifies a function of one argument that is used to extract\n a comparison key from each list element: ``key=str.lower``. The\n default value is ``None``.\n\n *reverse* is a boolean value. If set to ``True``, then the list\n elements are sorted as if each comparison were reversed.\n\n In general, the *key* and *reverse* conversion processes are much\n faster than specifying an equivalent *cmp* function. This is\n because *cmp* is called multiple times for each list element while\n *key* and *reverse* touch each element only once. Use\n ``functools.cmp_to_key()`` to convert an old-style *cmp* function\n to a *key* function.\n\n Changed in version 2.3: Support for ``None`` as an equivalent to\n omitting *cmp* was added.\n\n Changed in version 2.4: Support for *key* and *reverse* was added.\n\n9. Starting with Python 2.3, the ``sort()`` method is guaranteed to be\n stable. A sort is stable if it guarantees not to change the\n relative order of elements that compare equal --- this is helpful\n for sorting in multiple passes (for example, sort by department,\n then by salary grade).\n\n10. **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python 2.3 and newer makes the\n list appear empty for the duration, and raises ``ValueError`` if\n it can detect that the list has been mutated during a sort.\n", + 'typesseq': '\nSequence Types --- ``str``, ``unicode``, ``list``, ``tuple``, ``bytearray``, ``buffer``, ``xrange``\n***************************************************************************************************\n\nThere are seven sequence types: strings, Unicode strings, lists,\ntuples, bytearrays, buffers, and xrange objects.\n\nFor other containers see the built in ``dict`` and ``set`` classes,\nand the ``collections`` module.\n\nString literals are written in single or double quotes: ``\'xyzzy\'``,\n``"frobozz"``. See *String literals* for more about string literals.\nUnicode strings are much like strings, but are specified in the syntax\nusing a preceding ``\'u\'`` character: ``u\'abc\'``, ``u"def"``. In\naddition to the functionality described here, there are also string-\nspecific methods described in the *String Methods* section. Lists are\nconstructed with square brackets, separating items with commas: ``[a,\nb, c]``. Tuples are constructed by the comma operator (not within\nsquare brackets), with or without enclosing parentheses, but an empty\ntuple must have the enclosing parentheses, such as ``a, b, c`` or\n``()``. A single item tuple must have a trailing comma, such as\n``(d,)``.\n\nBytearray objects are created with the built-in function\n``bytearray()``.\n\nBuffer objects are not directly supported by Python syntax, but can be\ncreated by calling the built-in function ``buffer()``. They don\'t\nsupport concatenation or repetition.\n\nObjects of type xrange are similar to buffers in that there is no\nspecific syntax to create them, but they are created using the\n``xrange()`` function. They don\'t support slicing, concatenation or\nrepetition, and using ``in``, ``not in``, ``min()`` or ``max()`` on\nthem is inefficient.\n\nMost sequence types support the following operations. The ``in`` and\n``not in`` operations have the same priorities as the comparison\noperations. The ``+`` and ``*`` operations have the same priority as\nthe corresponding numeric operations. [3] Additional methods are\nprovided for *Mutable Sequence Types*.\n\nThis table lists the sequence operations sorted in ascending priority\n(operations in the same box have the same priority). In the table,\n*s* and *t* are sequences of the same type; *n*, *i* and *j* are\nintegers:\n\n+--------------------+----------------------------------+------------+\n| Operation | Result | Notes |\n+====================+==================================+============+\n| ``x in s`` | ``True`` if an item of *s* is | (1) |\n| | equal to *x*, else ``False`` | |\n+--------------------+----------------------------------+------------+\n| ``x not in s`` | ``False`` if an item of *s* is | (1) |\n| | equal to *x*, else ``True`` | |\n+--------------------+----------------------------------+------------+\n| ``s + t`` | the concatenation of *s* and *t* | (6) |\n+--------------------+----------------------------------+------------+\n| ``s * n, n * s`` | *n* shallow copies of *s* | (2) |\n| | concatenated | |\n+--------------------+----------------------------------+------------+\n| ``s[i]`` | *i*th item of *s*, origin 0 | (3) |\n+--------------------+----------------------------------+------------+\n| ``s[i:j]`` | slice of *s* from *i* to *j* | (3)(4) |\n+--------------------+----------------------------------+------------+\n| ``s[i:j:k]`` | slice of *s* from *i* to *j* | (3)(5) |\n| | with step *k* | |\n+--------------------+----------------------------------+------------+\n| ``len(s)`` | length of *s* | |\n+--------------------+----------------------------------+------------+\n| ``min(s)`` | smallest item of *s* | |\n+--------------------+----------------------------------+------------+\n| ``max(s)`` | largest item of *s* | |\n+--------------------+----------------------------------+------------+\n| ``s.index(i)`` | index of the first occurrence of | |\n| | *i* in *s* | |\n+--------------------+----------------------------------+------------+\n| ``s.count(i)`` | total number of occurrences of | |\n| | *i* in *s* | |\n+--------------------+----------------------------------+------------+\n\nSequence types also support comparisons. In particular, tuples and\nlists are compared lexicographically by comparing corresponding\nelements. This means that to compare equal, every element must compare\nequal and the two sequences must be of the same type and have the same\nlength. (For full details see *Comparisons* in the language\nreference.)\n\nNotes:\n\n1. When *s* is a string or Unicode string object the ``in`` and ``not\n in`` operations act like a substring test. In Python versions\n before 2.3, *x* had to be a string of length 1. In Python 2.3 and\n beyond, *x* may be a string of any length.\n\n2. Values of *n* less than ``0`` are treated as ``0`` (which yields an\n empty sequence of the same type as *s*). Note also that the copies\n are shallow; nested structures are not copied. This often haunts\n new Python programmers; consider:\n\n >>> lists = [[]] * 3\n >>> lists\n [[], [], []]\n >>> lists[0].append(3)\n >>> lists\n [[3], [3], [3]]\n\n What has happened is that ``[[]]`` is a one-element list containing\n an empty list, so all three elements of ``[[]] * 3`` are (pointers\n to) this single empty list. Modifying any of the elements of\n ``lists`` modifies this single list. You can create a list of\n different lists this way:\n\n >>> lists = [[] for i in range(3)]\n >>> lists[0].append(3)\n >>> lists[1].append(5)\n >>> lists[2].append(7)\n >>> lists\n [[3], [5], [7]]\n\n3. If *i* or *j* is negative, the index is relative to the end of the\n string: ``len(s) + i`` or ``len(s) + j`` is substituted. But note\n that ``-0`` is still ``0``.\n\n4. The slice of *s* from *i* to *j* is defined as the sequence of\n items with index *k* such that ``i <= k < j``. If *i* or *j* is\n greater than ``len(s)``, use ``len(s)``. If *i* is omitted or\n ``None``, use ``0``. If *j* is omitted or ``None``, use\n ``len(s)``. If *i* is greater than or equal to *j*, the slice is\n empty.\n\n5. The slice of *s* from *i* to *j* with step *k* is defined as the\n sequence of items with index ``x = i + n*k`` such that ``0 <= n <\n (j-i)/k``. In other words, the indices are ``i``, ``i+k``,\n ``i+2*k``, ``i+3*k`` and so on, stopping when *j* is reached (but\n never including *j*). If *i* or *j* is greater than ``len(s)``,\n use ``len(s)``. If *i* or *j* are omitted or ``None``, they become\n "end" values (which end depends on the sign of *k*). Note, *k*\n cannot be zero. If *k* is ``None``, it is treated like ``1``.\n\n6. **CPython implementation detail:** If *s* and *t* are both strings,\n some Python implementations such as CPython can usually perform an\n in-place optimization for assignments of the form ``s = s + t`` or\n ``s += t``. When applicable, this optimization makes quadratic\n run-time much less likely. This optimization is both version and\n implementation dependent. For performance sensitive code, it is\n preferable to use the ``str.join()`` method which assures\n consistent linear concatenation performance across versions and\n implementations.\n\n Changed in version 2.4: Formerly, string concatenation never\n occurred in-place.\n\n\nString Methods\n==============\n\nBelow are listed the string methods which both 8-bit strings and\nUnicode objects support. Some of them are also available on\n``bytearray`` objects.\n\nIn addition, Python\'s strings support the sequence type methods\ndescribed in the *Sequence Types --- str, unicode, list, tuple,\nbytearray, buffer, xrange* section. To output formatted strings use\ntemplate strings or the ``%`` operator described in the *String\nFormatting Operations* section. Also, see the ``re`` module for string\nfunctions based on regular expressions.\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is a space).\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.decode([encoding[, errors]])\n\n Decodes the string using the codec registered for *encoding*.\n *encoding* defaults to the default string encoding. *errors* may\n be given to set a different error handling scheme. The default is\n ``\'strict\'``, meaning that encoding errors raise ``UnicodeError``.\n Other possible values are ``\'ignore\'``, ``\'replace\'`` and any other\n name registered via ``codecs.register_error()``, see section *Codec\n Base Classes*.\n\n New in version 2.2.\n\n Changed in version 2.3: Support for other error handling schemes\n added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.encode([encoding[, errors]])\n\n Return an encoded version of the string. Default encoding is the\n current default string encoding. *errors* may be given to set a\n different error handling scheme. The default for *errors* is\n ``\'strict\'``, meaning that encoding errors raise a\n ``UnicodeError``. Other possible values are ``\'ignore\'``,\n ``\'replace\'``, ``\'xmlcharrefreplace\'``, ``\'backslashreplace\'`` and\n any other name registered via ``codecs.register_error()``, see\n section *Codec Base Classes*. For a list of possible encodings, see\n section *Standard Encodings*.\n\n New in version 2.0.\n\n Changed in version 2.3: Support for ``\'xmlcharrefreplace\'`` and\n ``\'backslashreplace\'`` and other error handling schemes added.\n\n Changed in version 2.7: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return ``True`` if the string ends with the specified *suffix*,\n otherwise return ``False``. *suffix* can also be a tuple of\n suffixes to look for. With optional *start*, test beginning at\n that position. With optional *end*, stop comparing at that\n position.\n\n Changed in version 2.5: Accept tuples as *suffix*.\n\nstr.expandtabs([tabsize])\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab (``\\t``), one or more space characters are inserted in the\n result until the current column is equal to the next tab position.\n (The tab character itself is not copied.) If the character is a\n newline (``\\n``) or return (``\\r``), it is copied and the current\n column is reset to zero. Any other character is copied unchanged\n and the current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice ``s[start:end]``.\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return ``-1`` if *sub* is not found.\n\n Note: The ``find()`` method should be used only if you need to know the\n position of *sub*. To check if *sub* is a substring or not, use\n the ``in`` operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces ``{}``. Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\n This method of string formatting is the new standard in Python 3,\n and should be preferred to the ``%`` formatting described in\n *String Formatting Operations* in new code.\n\n New in version 2.6.\n\nstr.index(sub[, start[, end]])\n\n Like ``find()``, but raise ``ValueError`` when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. The separator between elements is the\n string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to ``len(s)``.\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or ``None``, the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\n New in version 2.5.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within ``s[start:end]``.\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return ``-1`` on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like ``rfind()`` but raises ``ValueError`` when the substring *sub*\n is not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is a\n space). The original string is returned if *width* is less than or\n equal to ``len(s)``.\n\n Changed in version 2.4: Support for the *fillchar* argument.\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\n New in version 2.5.\n\nstr.rsplit([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n ``None``, any whitespace string is a separator. Except for\n splitting from the right, ``rsplit()`` behaves like ``split()``\n which is described in detail below.\n\n New in version 2.4.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or ``None``, the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.split([sep[, maxsplit]])\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most ``maxsplit+1``\n elements). If *maxsplit* is not specified or ``-1``, then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n ``\'1,,2\'.split(\',\')`` returns ``[\'1\', \'\', \'2\']``). The *sep*\n argument may consist of multiple characters (for example,\n ``\'1<>2<>3\'.split(\'<>\')`` returns ``[\'1\', \'2\', \'3\']``). Splitting\n an empty string with a specified separator returns ``[\'\']``.\n\n If *sep* is not specified or is ``None``, a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a ``None`` separator returns\n ``[]``.\n\n For example, ``\' 1 2 3 \'.split()`` returns ``[\'1\', \'2\', \'3\']``,\n and ``\' 1 2 3 \'.split(None, 1)`` returns ``[\'1\', \'2 3 \']``.\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example, ``\'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()`` returns\n ``[\'ab c\', \'\', \'de fg\', \'kl\']``, while the same call with\n ``splitlines(True)`` returns ``[\'ab c\\n\', \'\\n\', \'de fg\\r\',\n \'kl\\r\\n\']``.\n\n Unlike ``split()`` when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line.\n\nstr.startswith(prefix[, start[, end]])\n\n Return ``True`` if string starts with the *prefix*, otherwise\n return ``False``. *prefix* can also be a tuple of prefixes to look\n for. With optional *start*, test string beginning at that\n position. With optional *end*, stop comparing string at that\n position.\n\n Changed in version 2.5: Accept tuples as *prefix*.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or ``None``, the\n *chars* argument defaults to removing whitespace. The *chars*\n argument is not a prefix or suffix; rather, all combinations of its\n values are stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\n Changed in version 2.2.2: Support for the *chars* argument.\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa.\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.translate(table[, deletechars])\n\n Return a copy of the string where all characters occurring in the\n optional argument *deletechars* are removed, and the remaining\n characters have been mapped through the given translation table,\n which must be a string of length 256.\n\n You can use the ``maketrans()`` helper function in the ``string``\n module to create a translation table. For string objects, set the\n *table* argument to ``None`` for translations that only delete\n characters:\n\n >>> \'read this short text\'.translate(None, \'aeiou\')\n \'rd ths shrt txt\'\n\n New in version 2.6: Support for a ``None`` *table* argument.\n\n For Unicode objects, the ``translate()`` method does not accept the\n optional *deletechars* argument. Instead, it returns a copy of the\n *s* where all characters have been mapped through the given\n translation table which must be a mapping of Unicode ordinals to\n Unicode ordinals, Unicode strings or ``None``. Unmapped characters\n are left untouched. Characters mapped to ``None`` are deleted.\n Note, a more flexible approach is to create a custom character\n mapping codec using the ``codecs`` module (see ``encodings.cp1251``\n for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that ``str.upper().isupper()`` might\n be ``False`` if ``s`` contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n For 8-bit strings, this method is locale-dependent.\n\nstr.zfill(width)\n\n Return the numeric string left filled with zeros in a string of\n length *width*. A sign prefix is handled correctly. The original\n string is returned if *width* is less than or equal to ``len(s)``.\n\n New in version 2.2.2.\n\nThe following methods are present only on unicode objects:\n\nunicode.isnumeric()\n\n Return ``True`` if there are only numeric characters in S,\n ``False`` otherwise. Numeric characters include digit characters,\n and all characters that have the Unicode numeric value property,\n e.g. U+2155, VULGAR FRACTION ONE FIFTH.\n\nunicode.isdecimal()\n\n Return ``True`` if there are only decimal characters in S,\n ``False`` otherwise. Decimal characters include digit characters,\n and all characters that can be used to form decimal-radix numbers,\n e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\n\nString Formatting Operations\n============================\n\nString and Unicode objects have one unique built-in operation: the\n``%`` operator (modulo). This is also known as the string\n*formatting* or *interpolation* operator. Given ``format % values``\n(where *format* is a string or Unicode object), ``%`` conversion\nspecifications in *format* are replaced with zero or more elements of\n*values*. The effect is similar to the using ``sprintf()`` in the C\nlanguage. If *format* is a Unicode object, or if any of the objects\nbeing converted using the ``%s`` conversion are Unicode objects, the\nresult will also be a Unicode object.\n\nIf *format* requires a single argument, *values* may be a single non-\ntuple object. [5] Otherwise, *values* must be a tuple with exactly\nthe number of items specified by the format string, or a single\nmapping object (for example, a dictionary).\n\nA conversion specifier contains two or more characters and has the\nfollowing components, which must occur in this order:\n\n1. The ``\'%\'`` character, which marks the start of the specifier.\n\n2. Mapping key (optional), consisting of a parenthesised sequence of\n characters (for example, ``(somename)``).\n\n3. Conversion flags (optional), which affect the result of some\n conversion types.\n\n4. Minimum field width (optional). If specified as an ``\'*\'``\n (asterisk), the actual width is read from the next element of the\n tuple in *values*, and the object to convert comes after the\n minimum field width and optional precision.\n\n5. Precision (optional), given as a ``\'.\'`` (dot) followed by the\n precision. If specified as ``\'*\'`` (an asterisk), the actual width\n is read from the next element of the tuple in *values*, and the\n value to convert comes after the precision.\n\n6. Length modifier (optional).\n\n7. Conversion type.\n\nWhen the right argument is a dictionary (or other mapping type), then\nthe formats in the string *must* include a parenthesised mapping key\ninto that dictionary inserted immediately after the ``\'%\'`` character.\nThe mapping key selects the value to be formatted from the mapping.\nFor example:\n\n>>> print \'%(language)s has %(number)03d quote types.\' % \\\n... {"language": "Python", "number": 2}\nPython has 002 quote types.\n\nIn this case no ``*`` specifiers may occur in a format (since they\nrequire a sequential parameter list).\n\nThe conversion flag characters are:\n\n+-----------+-----------------------------------------------------------------------+\n| Flag | Meaning |\n+===========+=======================================================================+\n| ``\'#\'`` | The value conversion will use the "alternate form" (where defined |\n| | below). |\n+-----------+-----------------------------------------------------------------------+\n| ``\'0\'`` | The conversion will be zero padded for numeric values. |\n+-----------+-----------------------------------------------------------------------+\n| ``\'-\'`` | The converted value is left adjusted (overrides the ``\'0\'`` |\n| | conversion if both are given). |\n+-----------+-----------------------------------------------------------------------+\n| ``\' \'`` | (a space) A blank should be left before a positive number (or empty |\n| | string) produced by a signed conversion. |\n+-----------+-----------------------------------------------------------------------+\n| ``\'+\'`` | A sign character (``\'+\'`` or ``\'-\'``) will precede the conversion |\n| | (overrides a "space" flag). |\n+-----------+-----------------------------------------------------------------------+\n\nA length modifier (``h``, ``l``, or ``L``) may be present, but is\nignored as it is not necessary for Python -- so e.g. ``%ld`` is\nidentical to ``%d``.\n\nThe conversion types are:\n\n+--------------+-------------------------------------------------------+---------+\n| Conversion | Meaning | Notes |\n+==============+=======================================================+=========+\n| ``\'d\'`` | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'i\'`` | Signed integer decimal. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'o\'`` | Signed octal value. | (1) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'u\'`` | Obsolete type -- it is identical to ``\'d\'``. | (7) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'x\'`` | Signed hexadecimal (lowercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'X\'`` | Signed hexadecimal (uppercase). | (2) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'e\'`` | Floating point exponential format (lowercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'E\'`` | Floating point exponential format (uppercase). | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'f\'`` | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'F\'`` | Floating point decimal format. | (3) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'g\'`` | Floating point format. Uses lowercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'G\'`` | Floating point format. Uses uppercase exponential | (4) |\n| | format if exponent is less than -4 or not less than | |\n| | precision, decimal format otherwise. | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'c\'`` | Single character (accepts integer or single character | |\n| | string). | |\n+--------------+-------------------------------------------------------+---------+\n| ``\'r\'`` | String (converts any Python object using *repr()*). | (5) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'s\'`` | String (converts any Python object using ``str()``). | (6) |\n+--------------+-------------------------------------------------------+---------+\n| ``\'%\'`` | No argument is converted, results in a ``\'%\'`` | |\n| | character in the result. | |\n+--------------+-------------------------------------------------------+---------+\n\nNotes:\n\n1. The alternate form causes a leading zero (``\'0\'``) to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n2. The alternate form causes a leading ``\'0x\'`` or ``\'0X\'`` (depending\n on whether the ``\'x\'`` or ``\'X\'`` format was used) to be inserted\n between left-hand padding and the formatting of the number if the\n leading character of the result is not already a zero.\n\n3. The alternate form causes the result to always contain a decimal\n point, even if no digits follow it.\n\n The precision determines the number of digits after the decimal\n point and defaults to 6.\n\n4. The alternate form causes the result to always contain a decimal\n point, and trailing zeroes are not removed as they would otherwise\n be.\n\n The precision determines the number of significant digits before\n and after the decimal point and defaults to 6.\n\n5. The ``%r`` conversion was added in Python 2.0.\n\n The precision determines the maximal number of characters used.\n\n6. If the object or format provided is a ``unicode`` string, the\n resulting string will also be ``unicode``.\n\n The precision determines the maximal number of characters used.\n\n7. See **PEP 237**.\n\nSince Python strings have an explicit length, ``%s`` conversions do\nnot assume that ``\'\\0\'`` is the end of the string.\n\nChanged in version 2.7: ``%f`` conversions for numbers whose absolute\nvalue is over 1e50 are no longer replaced by ``%g`` conversions.\n\nAdditional string operations are defined in standard modules\n``string`` and ``re``.\n\n\nXRange Type\n===========\n\nThe ``xrange`` type is an immutable sequence which is commonly used\nfor looping. The advantage of the ``xrange`` type is that an\n``xrange`` object will always take the same amount of memory, no\nmatter the size of the range it represents. There are no consistent\nperformance advantages.\n\nXRange objects have very little behavior: they only support indexing,\niteration, and the ``len()`` function.\n\n\nMutable Sequence Types\n======================\n\nList and ``bytearray`` objects support additional operations that\nallow in-place modification of the object. Other mutable sequence\ntypes (when added to the language) should also support these\noperations. Strings and tuples are immutable sequence types: such\nobjects cannot be modified once created. The following operations are\ndefined on mutable sequence types (where *x* is an arbitrary object):\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | same as ``s[len(s):len(s)] = | (2) |\n| | [x]`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(x)`` | same as ``s[len(s):len(s)] = x`` | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.count(x)`` | return number of *i*\'s for which | |\n| | ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.index(x[, i[, j]])`` | return smallest *k* such that | (4) |\n| | ``s[k] == x`` and ``i <= k < j`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | same as ``s[i:i] = [x]`` | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | same as ``x = s[i]; del s[i]; | (6) |\n| | return x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | same as ``del s[s.index(x)]`` | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (7) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.sort([cmp[, key[, | sort the items of *s* in place | (7)(8)(9)(10) |\n| reverse]]])`` | | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The C implementation of Python has historically accepted multiple\n parameters and implicitly joined them into a tuple; this no longer\n works in Python 2.0. Use of this misfeature has been deprecated\n since Python 1.4.\n\n3. *x* can be any iterable object.\n\n4. Raises ``ValueError`` when *x* is not found in *s*. When a negative\n index is passed as the second or third parameter to the ``index()``\n method, the list length is added, as for slice indices. If it is\n still negative, it is truncated to zero, as for slice indices.\n\n Changed in version 2.3: Previously, ``index()`` didn\'t have\n arguments for specifying start and stop positions.\n\n5. When a negative index is passed as the first parameter to the\n ``insert()`` method, the list length is added, as for slice\n indices. If it is still negative, it is truncated to zero, as for\n slice indices.\n\n Changed in version 2.3: Previously, all negative indices were\n truncated to zero.\n\n6. The ``pop()`` method\'s optional argument *i* defaults to ``-1``, so\n that by default the last item is removed and returned.\n\n7. The ``sort()`` and ``reverse()`` methods modify the list in place\n for economy of space when sorting or reversing a large list. To\n remind you that they operate by side effect, they don\'t return the\n sorted or reversed list.\n\n8. The ``sort()`` method takes optional arguments for controlling the\n comparisons.\n\n *cmp* specifies a custom comparison function of two arguments (list\n items) which should return a negative, zero or positive number\n depending on whether the first argument is considered smaller than,\n equal to, or larger than the second argument: ``cmp=lambda x,y:\n cmp(x.lower(), y.lower())``. The default value is ``None``.\n\n *key* specifies a function of one argument that is used to extract\n a comparison key from each list element: ``key=str.lower``. The\n default value is ``None``.\n\n *reverse* is a boolean value. If set to ``True``, then the list\n elements are sorted as if each comparison were reversed.\n\n In general, the *key* and *reverse* conversion processes are much\n faster than specifying an equivalent *cmp* function. This is\n because *cmp* is called multiple times for each list element while\n *key* and *reverse* touch each element only once. Use\n ``functools.cmp_to_key()`` to convert an old-style *cmp* function\n to a *key* function.\n\n Changed in version 2.3: Support for ``None`` as an equivalent to\n omitting *cmp* was added.\n\n Changed in version 2.4: Support for *key* and *reverse* was added.\n\n9. Starting with Python 2.3, the ``sort()`` method is guaranteed to be\n stable. A sort is stable if it guarantees not to change the\n relative order of elements that compare equal --- this is helpful\n for sorting in multiple passes (for example, sort by department,\n then by salary grade).\n\n10. **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python 2.3 and newer makes the\n list appear empty for the duration, and raises ``ValueError`` if\n it can detect that the list has been mutated during a sort.\n', + 'typesseq-mutable': "\nMutable Sequence Types\n**********************\n\nList and ``bytearray`` objects support additional operations that\nallow in-place modification of the object. Other mutable sequence\ntypes (when added to the language) should also support these\noperations. Strings and tuples are immutable sequence types: such\nobjects cannot be modified once created. The following operations are\ndefined on mutable sequence types (where *x* is an arbitrary object):\n\n+--------------------------------+----------------------------------+-----------------------+\n| Operation | Result | Notes |\n+================================+==================================+=======================+\n| ``s[i] = x`` | item *i* of *s* is replaced by | |\n| | *x* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j] = t`` | slice of *s* from *i* to *j* is | |\n| | replaced by the contents of the | |\n| | iterable *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j]`` | same as ``s[i:j] = []`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s[i:j:k] = t`` | the elements of ``s[i:j:k]`` are | (1) |\n| | replaced by those of *t* | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``del s[i:j:k]`` | removes the elements of | |\n| | ``s[i:j:k]`` from the list | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.append(x)`` | same as ``s[len(s):len(s)] = | (2) |\n| | [x]`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.extend(x)`` | same as ``s[len(s):len(s)] = x`` | (3) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.count(x)`` | return number of *i*'s for which | |\n| | ``s[i] == x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.index(x[, i[, j]])`` | return smallest *k* such that | (4) |\n| | ``s[k] == x`` and ``i <= k < j`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.insert(i, x)`` | same as ``s[i:i] = [x]`` | (5) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.pop([i])`` | same as ``x = s[i]; del s[i]; | (6) |\n| | return x`` | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.remove(x)`` | same as ``del s[s.index(x)]`` | (4) |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.reverse()`` | reverses the items of *s* in | (7) |\n| | place | |\n+--------------------------------+----------------------------------+-----------------------+\n| ``s.sort([cmp[, key[, | sort the items of *s* in place | (7)(8)(9)(10) |\n| reverse]]])`` | | |\n+--------------------------------+----------------------------------+-----------------------+\n\nNotes:\n\n1. *t* must have the same length as the slice it is replacing.\n\n2. The C implementation of Python has historically accepted multiple\n parameters and implicitly joined them into a tuple; this no longer\n works in Python 2.0. Use of this misfeature has been deprecated\n since Python 1.4.\n\n3. *x* can be any iterable object.\n\n4. Raises ``ValueError`` when *x* is not found in *s*. When a negative\n index is passed as the second or third parameter to the ``index()``\n method, the list length is added, as for slice indices. If it is\n still negative, it is truncated to zero, as for slice indices.\n\n Changed in version 2.3: Previously, ``index()`` didn't have\n arguments for specifying start and stop positions.\n\n5. When a negative index is passed as the first parameter to the\n ``insert()`` method, the list length is added, as for slice\n indices. If it is still negative, it is truncated to zero, as for\n slice indices.\n\n Changed in version 2.3: Previously, all negative indices were\n truncated to zero.\n\n6. The ``pop()`` method's optional argument *i* defaults to ``-1``, so\n that by default the last item is removed and returned.\n\n7. The ``sort()`` and ``reverse()`` methods modify the list in place\n for economy of space when sorting or reversing a large list. To\n remind you that they operate by side effect, they don't return the\n sorted or reversed list.\n\n8. The ``sort()`` method takes optional arguments for controlling the\n comparisons.\n\n *cmp* specifies a custom comparison function of two arguments (list\n items) which should return a negative, zero or positive number\n depending on whether the first argument is considered smaller than,\n equal to, or larger than the second argument: ``cmp=lambda x,y:\n cmp(x.lower(), y.lower())``. The default value is ``None``.\n\n *key* specifies a function of one argument that is used to extract\n a comparison key from each list element: ``key=str.lower``. The\n default value is ``None``.\n\n *reverse* is a boolean value. If set to ``True``, then the list\n elements are sorted as if each comparison were reversed.\n\n In general, the *key* and *reverse* conversion processes are much\n faster than specifying an equivalent *cmp* function. This is\n because *cmp* is called multiple times for each list element while\n *key* and *reverse* touch each element only once. Use\n ``functools.cmp_to_key()`` to convert an old-style *cmp* function\n to a *key* function.\n\n Changed in version 2.3: Support for ``None`` as an equivalent to\n omitting *cmp* was added.\n\n Changed in version 2.4: Support for *key* and *reverse* was added.\n\n9. Starting with Python 2.3, the ``sort()`` method is guaranteed to be\n stable. A sort is stable if it guarantees not to change the\n relative order of elements that compare equal --- this is helpful\n for sorting in multiple passes (for example, sort by department,\n then by salary grade).\n\n10. **CPython implementation detail:** While a list is being sorted,\n the effect of attempting to mutate, or even inspect, the list is\n undefined. The C implementation of Python 2.3 and newer makes the\n list appear empty for the duration, and raises ``ValueError`` if\n it can detect that the list has been mutated during a sort.\n", 'unary': '\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary ``-`` (minus) operator yields the negation of its numeric\nargument.\n\nThe unary ``+`` (plus) operator yields its numeric argument unchanged.\n\nThe unary ``~`` (invert) operator yields the bitwise inversion of its\nplain or long integer argument. The bitwise inversion of ``x`` is\ndefined as ``-(x+1)``. It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n``TypeError`` exception is raised.\n', 'while': '\nThe ``while`` statement\n***********************\n\nThe ``while`` statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the ``else`` clause, if present, is\nexecuted and the loop terminates.\n\nA ``break`` statement executed in the first suite terminates the loop\nwithout executing the ``else`` clause\'s suite. A ``continue``\nstatement executed in the first suite skips the rest of the suite and\ngoes back to testing the expression.\n', 'with': '\nThe ``with`` statement\n**********************\n\nNew in version 2.5.\n\nThe ``with`` statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common\n``try``...``except``...``finally`` usage patterns to be encapsulated\nfor convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the ``with`` statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the ``with_item``)\n is evaluated to obtain a context manager.\n\n2. The context manager\'s ``__exit__()`` is loaded for later use.\n\n3. The context manager\'s ``__enter__()`` method is invoked.\n\n4. If a target was included in the ``with`` statement, the return\n value from ``__enter__()`` is assigned to it.\n\n Note: The ``with`` statement guarantees that if the ``__enter__()``\n method returns without an error, then ``__exit__()`` will always\n be called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s ``__exit__()`` method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to ``__exit__()``. Otherwise,\n three ``None`` arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the ``__exit__()`` method was false, the exception is\n reraised. If the return value was true, the exception is\n suppressed, and execution continues with the statement following\n the ``with`` statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from ``__exit__()`` is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple ``with`` statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nNote: In Python 2.5, the ``with`` statement is only allowed when the\n ``with_statement`` feature has been enabled. It is always enabled\n in Python 2.6.\n\nChanged in version 2.7: Support for multiple context expressions.\n\nSee also:\n\n **PEP 0343** - The "with" statement\n The specification, background, and examples for the Python\n ``with`` statement.\n', -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 14 07:54:42 2014 From: python-checkins at python.org (ned.deily) Date: Fri, 14 Feb 2014 07:54:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNjA1?= =?utf-8?q?=3A_Make_test=5Fsocket_getaddrinfo_OS_X_segfault_test_more_robu?= =?utf-8?b?c3Qu?= Message-ID: <3fQQLp1hcjz7Lkk@mail.python.org> http://hg.python.org/cpython/rev/6017d19669c3 changeset: 89188:6017d19669c3 branch: 2.7 user: Ned Deily date: Thu Feb 13 22:49:30 2014 -0800 summary: Issue #20605: Make test_socket getaddrinfo OS X segfault test more robust. files: Lib/test/test_socket.py | 10 ++++++++-- Misc/NEWS | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -663,9 +663,15 @@ socket.getaddrinfo(None, 0, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE) - # Issue 17269 + # Issue 17269: test workaround for OS X platform bug segfault if hasattr(socket, 'AI_NUMERICSERV'): - socket.getaddrinfo("localhost", None, 0, 0, 0, socket.AI_NUMERICSERV) + try: + # The arguments here are undefined and the call may succeed + # or fail. All we care here is that it doesn't segfault. + socket.getaddrinfo("localhost", None, 0, 0, 0, + socket.AI_NUMERICSERV) + except socket.gaierror: + pass def check_sendall_interrupted(self, with_timeout): # socketpair() is not stricly required, but it makes things easier. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -282,6 +282,8 @@ - Issue #19085: Added basic tests for all tkinter widget options. +- Issue #20605: Make test_socket getaddrinfo OS X segfault test more robust. + Documentation ------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 14 07:54:43 2014 From: python-checkins at python.org (ned.deily) Date: Fri, 14 Feb 2014 07:54:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNjA1?= =?utf-8?q?=3A_Make_test=5Fsocket_getaddrinfo_OS_X_segfault_test_more_robu?= =?utf-8?b?c3Qu?= Message-ID: <3fQQLq3JkFz7Lkk@mail.python.org> http://hg.python.org/cpython/rev/11a75f141cec changeset: 89189:11a75f141cec branch: 3.3 parent: 89180:b5ad525076eb user: Ned Deily date: Thu Feb 13 22:50:42 2014 -0800 summary: Issue #20605: Make test_socket getaddrinfo OS X segfault test more robust. files: Lib/test/test_socket.py | 10 ++++++++-- Misc/NEWS | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1164,9 +1164,15 @@ # Issue #6697. self.assertRaises(UnicodeEncodeError, socket.getaddrinfo, 'localhost', '\uD800') - # Issue 17269 + # Issue 17269: test workaround for OS X platform bug segfault if hasattr(socket, 'AI_NUMERICSERV'): - socket.getaddrinfo("localhost", None, 0, 0, 0, socket.AI_NUMERICSERV) + try: + # The arguments here are undefined and the call may succeed + # or fail. All we care here is that it doesn't segfault. + socket.getaddrinfo("localhost", None, 0, 0, 0, + socket.AI_NUMERICSERV) + except socket.gaierror: + pass def test_getnameinfo(self): # only IP addresses are allowed diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -116,6 +116,8 @@ - Issue #20474: Fix test_socket "unexpected success" failures on OS X 10.7+. +- Issue #20605: Make test_socket getaddrinfo OS X segfault test more robust. + Documentation ------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 14 07:54:44 2014 From: python-checkins at python.org (ned.deily) Date: Fri, 14 Feb 2014 07:54:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320605=3A_Make_test=5Fsocket_getaddrinfo_OS_X_se?= =?utf-8?q?gfault_test_more_robust=2E?= Message-ID: <3fQQLr5MRQz7Llg@mail.python.org> http://hg.python.org/cpython/rev/378bdb92e5b7 changeset: 89190:378bdb92e5b7 parent: 89186:2dd4922c9371 parent: 89189:11a75f141cec user: Ned Deily date: Thu Feb 13 22:53:42 2014 -0800 summary: Issue #20605: Make test_socket getaddrinfo OS X segfault test more robust. files: Lib/test/test_socket.py | 10 ++++++++-- Misc/NEWS | 5 +++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1234,9 +1234,15 @@ # Issue #6697. self.assertRaises(UnicodeEncodeError, socket.getaddrinfo, 'localhost', '\uD800') - # Issue 17269 + # Issue 17269: test workaround for OS X platform bug segfault if hasattr(socket, 'AI_NUMERICSERV'): - socket.getaddrinfo("localhost", None, 0, 0, 0, socket.AI_NUMERICSERV) + try: + # The arguments here are undefined and the call may succeed + # or fail. All we care here is that it doesn't segfault. + socket.getaddrinfo("localhost", None, 0, 0, 0, + socket.AI_NUMERICSERV) + except socket.gaierror: + pass def test_getnameinfo(self): # only IP addresses are allowed diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -33,6 +33,11 @@ - Issue #19856: shutil.move() failed to move a directory to other directory on Windows if source name ends with os.altsep. +Tests +----- + +- Issue #20605: Make test_socket getaddrinfo OS X segfault test more robust. + What's New in Python 3.4.0 release candidate 1? =============================================== -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Feb 14 08:56:15 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 14 Feb 2014 08:56:15 +0100 Subject: [Python-checkins] Daily reference leaks (2dd4922c9371): sum=-4 Message-ID: results for 2dd4922c9371 on branch "default" -------------------------------------------- test_site leaked [0, -2, 0] references, sum=-2 test_site leaked [0, -2, 0] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogvvQUGV', '-x'] From python-checkins at python.org Fri Feb 14 20:10:47 2014 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 14 Feb 2014 20:10:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_fix_links_to_b?= =?utf-8?q?uiltin_repr_function_=28closes_=2320573=29?= Message-ID: <3fQkh70s8sz7Ljg@mail.python.org> http://hg.python.org/cpython/rev/7c47529bda0e changeset: 89191:7c47529bda0e branch: 2.7 parent: 89188:6017d19669c3 user: Benjamin Peterson date: Fri Feb 14 14:10:39 2014 -0500 summary: fix links to builtin repr function (closes #20573) files: Doc/library/repr.rst | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Doc/library/repr.rst b/Doc/library/repr.rst --- a/Doc/library/repr.rst +++ b/Doc/library/repr.rst @@ -24,8 +24,9 @@ .. class:: Repr() Class which provides formatting services useful in implementing functions - similar to the built-in :func:`repr`; size limits for different object types - are added to avoid the generation of representations which are excessively long. + similar to the built-in :ref:`repr() `; size limits for different + object types are added to avoid the generation of representations which are + excessively long. .. data:: aRepr @@ -96,8 +97,8 @@ .. method:: Repr.repr(obj) - The equivalent to the built-in :func:`repr` that uses the formatting imposed by - the instance. + The equivalent to the built-in :ref:`repr() ` that uses the + formatting imposed by the instance. .. method:: Repr.repr1(obj, level) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 00:17:54 2014 From: python-checkins at python.org (nick.coghlan) Date: Sat, 15 Feb 2014 00:17:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2319744=3A_Handle_m?= =?utf-8?q?issing_SSL/TLS_in_ensurepip?= Message-ID: <3fQr9G2fXtz7LjY@mail.python.org> http://hg.python.org/cpython/rev/9f76adbac8b7 changeset: 89192:9f76adbac8b7 parent: 89190:378bdb92e5b7 user: Nick Coghlan date: Sat Feb 15 09:14:54 2014 +1000 summary: Issue #19744: Handle missing SSL/TLS in ensurepip - now also allows POSIX installation with SSL/TLS missing - a goal for pip 1.6 is to allow local use without SSL/TLS files: Lib/ensurepip/__init__.py | 5 +++++ Lib/test/test_ensurepip.py | 8 ++++++++ Misc/NEWS | 4 ++++ 3 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -144,6 +144,11 @@ def _main(argv=None): + if ssl is None: + print("Ignoring ensurepip failure: {}".format(_MISSING_SSL_MESSAGE), + file=sys.stderr) + return + import argparse parser = argparse.ArgumentParser(prog="python -m ensurepip") parser.add_argument( diff --git a/Lib/test/test_ensurepip.py b/Lib/test/test_ensurepip.py --- a/Lib/test/test_ensurepip.py +++ b/Lib/test/test_ensurepip.py @@ -281,12 +281,20 @@ self.run_pip.assert_not_called() self.assertIn("PIP_THIS_SHOULD_STAY", self.os_environ) + def test_main_exits_early_with_warning(self): + with test.support.captured_stderr() as stderr: + ensurepip_no_ssl._main(["--version"]) + warning = stderr.getvalue().strip() + self.assertTrue(warning.endswith("requires SSL/TLS"), warning) + self.run_pip.assert_not_called() + # Basic testing of the main functions and their argument parsing EXPECTED_VERSION_OUTPUT = "pip " + ensurepip._PIP_VERSION class TestBootstrappingMainFunction(EnsurepipMixin, unittest.TestCase): + @requires_usable_pip def test_bootstrap_version(self): with test.support.captured_stdout() as stdout: with self.assertRaises(SystemExit): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,10 @@ Library ------- +- Issue #19744: the ensurepip installation step now just prints a warning to + stderr rather than failing outright if SSL/TLS is unavailable. This allows + local installation of POSIX builds without SSL/TLS support. + - Issue #6815: os.path.expandvars() now supports non-ASCII environment variables names and values. -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sat Feb 15 09:43:39 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 15 Feb 2014 09:43:39 +0100 Subject: [Python-checkins] Daily reference leaks (9f76adbac8b7): sum=4 Message-ID: results for 9f76adbac8b7 on branch "default" -------------------------------------------- test_site leaked [0, 2, 0] references, sum=2 test_site leaked [0, 2, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogVNNFr_', '-x'] From python-checkins at python.org Sat Feb 15 12:02:00 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 15 Feb 2014 12:02:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzIwNjM0OiBmaXgg?= =?utf-8?q?typo_in_IDLE_README_noticed_by_Saimadhav_Heblikar=2E?= Message-ID: <3fR7nh4tHXz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/2c6deff0e522 changeset: 89193:2c6deff0e522 branch: 2.7 parent: 89191:7c47529bda0e user: Ezio Melotti date: Sat Feb 15 13:01:08 2014 +0200 summary: #20634: fix typo in IDLE README noticed by Saimadhav Heblikar. files: Lib/idlelib/idle_test/README.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -105,4 +105,4 @@ To run an individual Testcase or test method, extend the dotted name given to unittest on the command line. (But gui tests will not this way.) -python -m unittest -v idlelib.idle_test.text_xyz.Test_case.test_meth +python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 12:02:01 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 15 Feb 2014 12:02:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzIwNjM0OiBmaXgg?= =?utf-8?q?typo_in_IDLE_README_noticed_by_Saimadhav_Heblikar=2E?= Message-ID: <3fR7nj6Gn8z7Lll@mail.python.org> http://hg.python.org/cpython/rev/be42b12065d7 changeset: 89194:be42b12065d7 branch: 3.3 parent: 89189:11a75f141cec user: Ezio Melotti date: Sat Feb 15 13:01:08 2014 +0200 summary: #20634: fix typo in IDLE README noticed by Saimadhav Heblikar. files: Lib/idlelib/idle_test/README.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -105,4 +105,4 @@ To run an individual Testcase or test method, extend the dotted name given to unittest on the command line. (But gui tests will not this way.) -python -m unittest -v idlelib.idle_test.text_xyz.Test_case.test_meth +python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 12:02:03 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 15 Feb 2014 12:02:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzIwNjM0OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3fR7nl0zTfz7Llb@mail.python.org> http://hg.python.org/cpython/rev/dcbbff7e6b56 changeset: 89195:dcbbff7e6b56 parent: 89192:9f76adbac8b7 parent: 89194:be42b12065d7 user: Ezio Melotti date: Sat Feb 15 13:01:41 2014 +0200 summary: #20634: merge with 3.3. files: Lib/idlelib/idle_test/README.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -105,4 +105,4 @@ To run an individual Testcase or test method, extend the dotted name given to unittest on the command line. (But gui tests will not this way.) -python -m unittest -v idlelib.idle_test.text_xyz.Test_case.test_meth +python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 15:59:57 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 15 Feb 2014 15:59:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE5ODkwOiBmaXgg?= =?utf-8?q?typo_in_multiprocessing_docs=2E__Patch_by_Mike_Short=2E?= Message-ID: <3fRF4F0hGhzS4l@mail.python.org> http://hg.python.org/cpython/rev/655dffe47b5a changeset: 89196:655dffe47b5a branch: 2.7 parent: 89193:2c6deff0e522 user: Ezio Melotti date: Sat Feb 15 16:58:52 2014 +0200 summary: #19890: fix typo in multiprocessing docs. Patch by Mike Short. files: Doc/library/multiprocessing.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1257,7 +1257,7 @@ *exposed* is used to specify a sequence of method names which proxies for this typeid should be allowed to access using - :meth:`BaseProxy._callMethod`. (If *exposed* is ``None`` then + :meth:`BaseProxy._callmethod`. (If *exposed* is ``None`` then :attr:`proxytype._exposed_` is used instead if it exists.) In the case where no exposed list is specified, all "public methods" of the shared object will be accessible. (Here a "public method" means any attribute -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 15:59:58 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 15 Feb 2014 15:59:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE5ODkwOiBmaXgg?= =?utf-8?q?typo_in_multiprocessing_docs=2E__Patch_by_Mike_Short=2E?= Message-ID: <3fRF4G26P5z7LlQ@mail.python.org> http://hg.python.org/cpython/rev/f45d4823f63c changeset: 89197:f45d4823f63c branch: 3.3 parent: 89194:be42b12065d7 user: Ezio Melotti date: Sat Feb 15 16:58:52 2014 +0200 summary: #19890: fix typo in multiprocessing docs. Patch by Mike Short. files: Doc/library/multiprocessing.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1306,7 +1306,7 @@ *exposed* is used to specify a sequence of method names which proxies for this typeid should be allowed to access using - :meth:`BaseProxy._callMethod`. (If *exposed* is ``None`` then + :meth:`BaseProxy._callmethod`. (If *exposed* is ``None`` then :attr:`proxytype._exposed_` is used instead if it exists.) In the case where no exposed list is specified, all "public methods" of the shared object will be accessible. (Here a "public method" means any attribute -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 15:59:59 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 15 Feb 2014 15:59:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE5ODkwOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3fRF4H3YWSz7LlH@mail.python.org> http://hg.python.org/cpython/rev/72f9b6222476 changeset: 89198:72f9b6222476 parent: 89195:dcbbff7e6b56 parent: 89197:f45d4823f63c user: Ezio Melotti date: Sat Feb 15 16:59:39 2014 +0200 summary: #19890: merge with 3.3. files: Doc/library/multiprocessing.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1474,7 +1474,7 @@ *exposed* is used to specify a sequence of method names which proxies for this typeid should be allowed to access using - :meth:`BaseProxy._callMethod`. (If *exposed* is ``None`` then + :meth:`BaseProxy._callmethod`. (If *exposed* is ``None`` then :attr:`proxytype._exposed_` is used instead if it exists.) In the case where no exposed list is specified, all "public methods" of the shared object will be accessible. (Here a "public method" means any attribute -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 19:03:28 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 15 Feb 2014 19:03:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_give_non-itera?= =?utf-8?q?ble_TypeError_a_message_=28closes_=2320507=29?= Message-ID: <3fRK806jnBz7LjN@mail.python.org> http://hg.python.org/cpython/rev/b9947b68ab61 changeset: 89199:b9947b68ab61 branch: 3.3 parent: 89197:f45d4823f63c user: Benjamin Peterson date: Sat Feb 15 13:02:52 2014 -0500 summary: give non-iterable TypeError a message (closes #20507) files: Objects/unicodeobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -9493,7 +9493,7 @@ PyObject *last_obj; unsigned int kind = 0; - fseq = PySequence_Fast(seq, ""); + fseq = PySequence_Fast(seq, "can only join an iterable"); if (fseq == NULL) { return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 19:03:30 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 15 Feb 2014 19:03:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_give_non-itera?= =?utf-8?q?ble_TypeError_a_message_=28closes_=2320507=29?= Message-ID: <3fRK8218Q2z7Ljc@mail.python.org> http://hg.python.org/cpython/rev/f8e1fdf79823 changeset: 89200:f8e1fdf79823 branch: 2.7 parent: 89196:655dffe47b5a user: Benjamin Peterson date: Sat Feb 15 13:02:52 2014 -0500 summary: give non-iterable TypeError a message (closes #20507) files: Objects/unicodeobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -5618,7 +5618,7 @@ PyObject *item; Py_ssize_t i; - fseq = PySequence_Fast(seq, ""); + fseq = PySequence_Fast(seq, "can only join an iterable"); if (fseq == NULL) { return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 19:03:31 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 15 Feb 2014 19:03:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4zICgjMjA1MDcp?= Message-ID: <3fRK832p0mz7LlH@mail.python.org> http://hg.python.org/cpython/rev/b077ee45f14f changeset: 89201:b077ee45f14f parent: 89198:72f9b6222476 parent: 89199:b9947b68ab61 user: Benjamin Peterson date: Sat Feb 15 13:03:20 2014 -0500 summary: merge 3.3 (#20507) files: Objects/unicodeobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -9666,7 +9666,7 @@ PyObject *last_obj; unsigned int kind = 0; - fseq = PySequence_Fast(seq, ""); + fseq = PySequence_Fast(seq, "can only join an iterable"); if (fseq == NULL) { return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 19:20:48 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 15 Feb 2014 19:20:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_add_missing_te?= =?utf-8?q?st_assertion_=28closes_=2320080=29?= Message-ID: <3fRKX04CXRz7LjV@mail.python.org> http://hg.python.org/cpython/rev/a87f284e14ea changeset: 89202:a87f284e14ea branch: 2.7 parent: 89200:f8e1fdf79823 user: Benjamin Peterson date: Sat Feb 15 13:19:59 2014 -0500 summary: add missing test assertion (closes #20080) Patch by Vajrasky Kok. files: Lib/sqlite3/test/factory.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/sqlite3/test/factory.py b/Lib/sqlite3/test/factory.py --- a/Lib/sqlite3/test/factory.py +++ b/Lib/sqlite3/test/factory.py @@ -112,6 +112,7 @@ self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() t = tuple(row) + self.assertEqual(t, (row['a'], row['b'])) def CheckSqliteRowAsDict(self): """Checks if the row object can be correctly converted to a dictionary""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 19:20:49 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 15 Feb 2014 19:20:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_add_missing_te?= =?utf-8?q?st_assertion_=28closes_=2320080=29?= Message-ID: <3fRKX15zLvz7Ljg@mail.python.org> http://hg.python.org/cpython/rev/66c7791d9841 changeset: 89203:66c7791d9841 branch: 3.3 parent: 89199:b9947b68ab61 user: Benjamin Peterson date: Sat Feb 15 13:19:59 2014 -0500 summary: add missing test assertion (closes #20080) Patch by Vajrasky Kok. files: Lib/sqlite3/test/factory.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/sqlite3/test/factory.py b/Lib/sqlite3/test/factory.py --- a/Lib/sqlite3/test/factory.py +++ b/Lib/sqlite3/test/factory.py @@ -112,6 +112,7 @@ self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() t = tuple(row) + self.assertEqual(t, (row['a'], row['b'])) def CheckSqliteRowAsDict(self): """Checks if the row object can be correctly converted to a dictionary""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 19:20:51 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 15 Feb 2014 19:20:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4zICgjMjAwODAp?= Message-ID: <3fRKX30By0z7LkW@mail.python.org> http://hg.python.org/cpython/rev/93d7f8223370 changeset: 89204:93d7f8223370 parent: 89201:b077ee45f14f parent: 89203:66c7791d9841 user: Benjamin Peterson date: Sat Feb 15 13:20:28 2014 -0500 summary: merge 3.3 (#20080) files: Lib/sqlite3/test/factory.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/sqlite3/test/factory.py b/Lib/sqlite3/test/factory.py --- a/Lib/sqlite3/test/factory.py +++ b/Lib/sqlite3/test/factory.py @@ -112,6 +112,7 @@ self.con.row_factory = sqlite.Row row = self.con.execute("select 1 as a, 2 as b").fetchone() t = tuple(row) + self.assertEqual(t, (row['a'], row['b'])) def CheckSqliteRowAsDict(self): """Checks if the row object can be correctly converted to a dictionary""" -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 21:33:59 2014 From: python-checkins at python.org (andrew.kuchling) Date: Sat, 15 Feb 2014 21:33:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzIwMjM3OiBtYWtl?= =?utf-8?q?_a_revision_pass_over_the_XML_vulnerabilities_section?= Message-ID: <3fRNTg4qMnzSVp@mail.python.org> http://hg.python.org/cpython/rev/1c93895c32d8 changeset: 89205:1c93895c32d8 branch: 3.3 parent: 89203:66c7791d9841 user: Andrew Kuchling date: Sat Feb 15 15:33:44 2014 -0500 summary: #20237: make a revision pass over the XML vulnerabilities section files: Doc/library/xml.rst | 73 +++++++++++++++----------------- 1 files changed, 35 insertions(+), 38 deletions(-) diff --git a/Doc/library/xml.rst b/Doc/library/xml.rst --- a/Doc/library/xml.rst +++ b/Doc/library/xml.rst @@ -14,9 +14,9 @@ .. warning:: The XML modules are not secure against erroneous or maliciously - constructed data. If you need to parse untrusted or unauthenticated data see - :ref:`xml-vulnerabilities`. - + constructed data. If you need to parse untrusted or + unauthenticated data see the :ref:`xml-vulnerabilities` and + :ref:`defused-packages` sections. It is important to note that modules in the :mod:`xml` package require that there be at least one SAX-compliant XML parser available. The Expat parser is @@ -46,16 +46,15 @@ .. _xml-vulnerabilities: XML vulnerabilities -=================== +------------------- The XML processing modules are not secure against maliciously constructed data. -An attacker can abuse vulnerabilities for e.g. denial of service attacks, to -access local files, to generate network connections to other machines, or -to or circumvent firewalls. The attacks on XML abuse unfamiliar features -like inline `DTD`_ (document type definition) with entities. +An attacker can abuse XML features to carry out denial of service attacks, +access local files, generate network connections to other machines, or +circumvent firewalls. -The following table gives an overview of the known attacks and if the various -modules are vulnerable to them. +The following table gives an overview of the known attacks and whether +the various modules are vulnerable to them. ========================= ======== ========= ========= ======== ========= kind sax etree minidom pulldom xmlrpc @@ -68,7 +67,7 @@ ========================= ======== ========= ========= ======== ========= 1. :mod:`xml.etree.ElementTree` doesn't expand external entities and raises a - ParserError when an entity occurs. + :exc:`ParserError` when an entity occurs. 2. :mod:`xml.dom.minidom` doesn't expand external entities and simply returns the unexpanded entity verbatim. 3. :mod:`xmlrpclib` doesn't expand external entities and omits them. @@ -77,23 +76,21 @@ billion laughs / exponential entity expansion The `Billion Laughs`_ attack -- also known as exponential entity expansion -- uses multiple levels of nested entities. Each entity refers to another entity - several times, the final entity definition contains a small string. Eventually - the small string is expanded to several gigabytes. The exponential expansion - consumes lots of CPU time, too. + several times, and the final entity definition contains a small string. + The exponential expansion results in several gigabytes of text and + consumes lots of memory and CPU time. quadratic blowup entity expansion A quadratic blowup attack is similar to a `Billion Laughs`_ attack; it abuses entity expansion, too. Instead of nested entities it repeats one large entity with a couple of thousand chars over and over again. The attack isn't as - efficient as the exponential case but it avoids triggering countermeasures of - parsers against heavily nested entities. + efficient as the exponential case but it avoids triggering parser countermeasures + that forbid deeply-nested entities. external entity expansion Entity declarations can contain more than just text for replacement. They can - also point to external resources by public identifiers or system identifiers. - System identifiers are standard URIs or can refer to local files. The XML - parser retrieves the resource with e.g. HTTP or FTP requests and embeds the - content into the XML document. + also point to external resources or local files. The XML + parser accesses the resource and embeds the content into the XML document. DTD retrieval Some XML libraries like Python's :mod:`xml.dom.pulldom` retrieve document type @@ -101,31 +98,32 @@ implications as the external entity expansion issue. decompression bomb - The issue of decompression bombs (aka `ZIP bomb`_) apply to all XML libraries - that can parse compressed XML stream like gzipped HTTP streams or LZMA-ed + Decompression bombs (aka `ZIP bomb`_) apply to all XML libraries + that can parse compressed XML streams such as gzipped HTTP streams or + LZMA-compressed files. For an attacker it can reduce the amount of transmitted data by three magnitudes or more. -The documentation of `defusedxml`_ on PyPI has further information about +The documentation for `defusedxml`_ on PyPI has further information about all known attack vectors with examples and references. -defused packages ----------------- +.. _defused-packages: + +The :mod:`defusedxml` and :mod:`defusedexpat` Packages +------------------------------------------------------ `defusedxml`_ is a pure Python package with modified subclasses of all stdlib -XML parsers that prevent any potentially malicious operation. The courses of -action are recommended for any server code that parses untrusted XML data. The -package also ships with example exploits and an extended documentation on more -XML exploits like xpath injection. +XML parsers that prevent any potentially malicious operation. Use of this +package is recommended for any server code that parses untrusted XML data. The +package also ships with example exploits and extended documentation on more +XML exploits such as XPath injection. -`defusedexpat`_ provides a modified libexpat and patched replacment -:mod:`pyexpat` extension module with countermeasures against entity expansion -DoS attacks. Defusedexpat still allows a sane and configurable amount of entity -expansions. The modifications will be merged into future releases of Python. - -The workarounds and modifications are not included in patch releases as they -break backward compatibility. After all inline DTD and entity expansion are -well-definied XML features. +`defusedexpat`_ provides a modified libexpat and a patched +:mod:`pyexpat` module that have countermeasures against entity expansion +DoS attacks. The :mod:`defusedexpat` module still allows a sane and configurable amount of entity +expansions. The modifications may be included in some future release of Python, +but will not be included in any bugfix releases of +Python because they break backward compatibility. .. _defusedxml: https://pypi.python.org/pypi/defusedxml/ @@ -133,4 +131,3 @@ .. _Billion Laughs: http://en.wikipedia.org/wiki/Billion_laughs .. _ZIP bomb: http://en.wikipedia.org/wiki/Zip_bomb .. _DTD: http://en.wikipedia.org/wiki/Document_Type_Definition - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 21:39:07 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 15 Feb 2014 21:39:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4z?= Message-ID: <3fRNbb5TlyzSVp@mail.python.org> http://hg.python.org/cpython/rev/1c0bc2514603 changeset: 89206:1c0bc2514603 parent: 89204:93d7f8223370 parent: 89205:1c93895c32d8 user: Benjamin Peterson date: Sat Feb 15 15:39:01 2014 -0500 summary: merge 3.3 files: Doc/library/xml.rst | 73 +++++++++++++++----------------- 1 files changed, 35 insertions(+), 38 deletions(-) diff --git a/Doc/library/xml.rst b/Doc/library/xml.rst --- a/Doc/library/xml.rst +++ b/Doc/library/xml.rst @@ -14,9 +14,9 @@ .. warning:: The XML modules are not secure against erroneous or maliciously - constructed data. If you need to parse untrusted or unauthenticated data see - :ref:`xml-vulnerabilities`. - + constructed data. If you need to parse untrusted or + unauthenticated data see the :ref:`xml-vulnerabilities` and + :ref:`defused-packages` sections. It is important to note that modules in the :mod:`xml` package require that there be at least one SAX-compliant XML parser available. The Expat parser is @@ -46,16 +46,15 @@ .. _xml-vulnerabilities: XML vulnerabilities -=================== +------------------- The XML processing modules are not secure against maliciously constructed data. -An attacker can abuse vulnerabilities for e.g. denial of service attacks, to -access local files, to generate network connections to other machines, or -to or circumvent firewalls. The attacks on XML abuse unfamiliar features -like inline `DTD`_ (document type definition) with entities. +An attacker can abuse XML features to carry out denial of service attacks, +access local files, generate network connections to other machines, or +circumvent firewalls. -The following table gives an overview of the known attacks and if the various -modules are vulnerable to them. +The following table gives an overview of the known attacks and whether +the various modules are vulnerable to them. ========================= ======== ========= ========= ======== ========= kind sax etree minidom pulldom xmlrpc @@ -68,7 +67,7 @@ ========================= ======== ========= ========= ======== ========= 1. :mod:`xml.etree.ElementTree` doesn't expand external entities and raises a - ParserError when an entity occurs. + :exc:`ParserError` when an entity occurs. 2. :mod:`xml.dom.minidom` doesn't expand external entities and simply returns the unexpanded entity verbatim. 3. :mod:`xmlrpclib` doesn't expand external entities and omits them. @@ -77,23 +76,21 @@ billion laughs / exponential entity expansion The `Billion Laughs`_ attack -- also known as exponential entity expansion -- uses multiple levels of nested entities. Each entity refers to another entity - several times, the final entity definition contains a small string. Eventually - the small string is expanded to several gigabytes. The exponential expansion - consumes lots of CPU time, too. + several times, and the final entity definition contains a small string. + The exponential expansion results in several gigabytes of text and + consumes lots of memory and CPU time. quadratic blowup entity expansion A quadratic blowup attack is similar to a `Billion Laughs`_ attack; it abuses entity expansion, too. Instead of nested entities it repeats one large entity with a couple of thousand chars over and over again. The attack isn't as - efficient as the exponential case but it avoids triggering countermeasures of - parsers against heavily nested entities. + efficient as the exponential case but it avoids triggering parser countermeasures + that forbid deeply-nested entities. external entity expansion Entity declarations can contain more than just text for replacement. They can - also point to external resources by public identifiers or system identifiers. - System identifiers are standard URIs or can refer to local files. The XML - parser retrieves the resource with e.g. HTTP or FTP requests and embeds the - content into the XML document. + also point to external resources or local files. The XML + parser accesses the resource and embeds the content into the XML document. DTD retrieval Some XML libraries like Python's :mod:`xml.dom.pulldom` retrieve document type @@ -101,31 +98,32 @@ implications as the external entity expansion issue. decompression bomb - The issue of decompression bombs (aka `ZIP bomb`_) apply to all XML libraries - that can parse compressed XML stream like gzipped HTTP streams or LZMA-ed + Decompression bombs (aka `ZIP bomb`_) apply to all XML libraries + that can parse compressed XML streams such as gzipped HTTP streams or + LZMA-compressed files. For an attacker it can reduce the amount of transmitted data by three magnitudes or more. -The documentation of `defusedxml`_ on PyPI has further information about +The documentation for `defusedxml`_ on PyPI has further information about all known attack vectors with examples and references. -defused packages ----------------- +.. _defused-packages: + +The :mod:`defusedxml` and :mod:`defusedexpat` Packages +------------------------------------------------------ `defusedxml`_ is a pure Python package with modified subclasses of all stdlib -XML parsers that prevent any potentially malicious operation. The courses of -action are recommended for any server code that parses untrusted XML data. The -package also ships with example exploits and an extended documentation on more -XML exploits like xpath injection. +XML parsers that prevent any potentially malicious operation. Use of this +package is recommended for any server code that parses untrusted XML data. The +package also ships with example exploits and extended documentation on more +XML exploits such as XPath injection. -`defusedexpat`_ provides a modified libexpat and patched replacment -:mod:`pyexpat` extension module with countermeasures against entity expansion -DoS attacks. Defusedexpat still allows a sane and configurable amount of entity -expansions. The modifications will be merged into future releases of Python. - -The workarounds and modifications are not included in patch releases as they -break backward compatibility. After all inline DTD and entity expansion are -well-definied XML features. +`defusedexpat`_ provides a modified libexpat and a patched +:mod:`pyexpat` module that have countermeasures against entity expansion +DoS attacks. The :mod:`defusedexpat` module still allows a sane and configurable amount of entity +expansions. The modifications may be included in some future release of Python, +but will not be included in any bugfix releases of +Python because they break backward compatibility. .. _defusedxml: https://pypi.python.org/pypi/defusedxml/ @@ -133,4 +131,3 @@ .. _Billion Laughs: http://en.wikipedia.org/wiki/Billion_laughs .. _ZIP bomb: http://en.wikipedia.org/wiki/Zip_bomb .. _DTD: http://en.wikipedia.org/wiki/Document_Type_Definition - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 22:39:48 2014 From: python-checkins at python.org (andrew.kuchling) Date: Sat, 15 Feb 2014 22:39:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Clarify_versio?= =?utf-8?q?nchanged_sentence=2E__Closes_=2320497=2E?= Message-ID: <3fRPxc0K1szQv8@mail.python.org> http://hg.python.org/cpython/rev/3352b5abe1e4 changeset: 89207:3352b5abe1e4 branch: 3.3 parent: 89205:1c93895c32d8 user: Andrew Kuchling date: Sat Feb 15 16:39:37 2014 -0500 summary: Clarify versionchanged sentence. Closes #20497. files: Doc/library/socket.rst | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -434,7 +434,7 @@ (10, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0))] .. versionchanged:: 3.2 - parameters can now be passed as single keyword arguments. + parameters can now be passed using keyword arguments. .. function:: getfqdn([name]) @@ -1437,4 +1437,3 @@ details of socket semantics. For Unix, refer to the manual pages; for Windows, see the WinSock (or Winsock 2) specification. For IPv6-ready APIs, readers may want to refer to :rfc:`3493` titled Basic Socket Interface Extensions for IPv6. - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 22:40:23 2014 From: python-checkins at python.org (andrew.kuchling) Date: Sat, 15 Feb 2014 22:40:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E3?= Message-ID: <3fRPyH6WWqz7Ljb@mail.python.org> http://hg.python.org/cpython/rev/8a1d3551881f changeset: 89208:8a1d3551881f parent: 89206:1c0bc2514603 parent: 89207:3352b5abe1e4 user: Andrew Kuchling date: Sat Feb 15 16:40:08 2014 -0500 summary: Merge from 3.3 files: Doc/library/socket.rst | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -468,7 +468,7 @@ (10, 1, 6, '', ('2001:888:2000:d::a2', 80, 0, 0))] .. versionchanged:: 3.2 - parameters can now be passed as single keyword arguments. + parameters can now be passed using keyword arguments. .. function:: getfqdn([name]) @@ -1512,4 +1512,3 @@ details of socket semantics. For Unix, refer to the manual pages; for Windows, see the WinSock (or Winsock 2) specification. For IPv6-ready APIs, readers may want to refer to :rfc:`3493` titled Basic Socket Interface Extensions for IPv6. - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 23:11:18 2014 From: python-checkins at python.org (andrew.kuchling) Date: Sat, 15 Feb 2014 23:11:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzE2NzI4OiBNZW50?= =?utf-8?q?ion_collections=2Eabc=2ESequence_in_=27sequence=27_glossary_ent?= =?utf-8?q?ry?= Message-ID: <3fRQdy176xz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/30d0816939a3 changeset: 89209:30d0816939a3 branch: 3.3 parent: 89207:3352b5abe1e4 user: Andrew Kuchling date: Sat Feb 15 17:05:26 2014 -0500 summary: #16728: Mention collections.abc.Sequence in 'sequence' glossary entry files: Doc/glossary.rst | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -763,6 +763,14 @@ mapping rather than a sequence because the lookups use arbitrary :term:`immutable` keys rather than integers. + The :class:`collections.abc.Sequence` abstract base class + defines a much richer interface that goes beyond just + :meth:`__getitem__` and :meth:`__len__`, adding :meth:`count`, + :meth:`index`, :meth:`__contains__`, and + :meth:`__reversed__`. Types that implement this expanded + interface can be registered explicitly using + :func:`~abc.register`. + slice An object usually containing a portion of a :term:`sequence`. A slice is created using the subscript notation, ``[]`` with colons between numbers -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 23:11:19 2014 From: python-checkins at python.org (andrew.kuchling) Date: Sat, 15 Feb 2014 23:11:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzIwMjQxOiB1c2Ug?= =?utf-8?q?correct_RFC_number?= Message-ID: <3fRQdz2P1Qz7Ljs@mail.python.org> http://hg.python.org/cpython/rev/383f4eede628 changeset: 89210:383f4eede628 branch: 3.3 user: Andrew Kuchling date: Sat Feb 15 17:11:06 2014 -0500 summary: #20241: use correct RFC number files: Doc/library/ipaddress.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -165,7 +165,7 @@ .. attribute:: is_unspecified - ``True`` if the address is unspecified. See :RFC:`5375` (for IPv4) + ``True`` if the address is unspecified. See :RFC:`5735` (for IPv4) or :RFC:`2373` (for IPv6). .. attribute:: is_reserved -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 15 23:22:56 2014 From: python-checkins at python.org (andrew.kuchling) Date: Sat, 15 Feb 2014 23:22:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E3?= Message-ID: <3fRQvN0GVqzSNd@mail.python.org> http://hg.python.org/cpython/rev/2d62ee3c7617 changeset: 89211:2d62ee3c7617 parent: 89208:8a1d3551881f parent: 89210:383f4eede628 user: Andrew Kuchling date: Sat Feb 15 17:22:41 2014 -0500 summary: Merge from 3.3 files: Doc/glossary.rst | 8 ++++++++ Doc/library/ipaddress.rst | 2 +- 2 files changed, 9 insertions(+), 1 deletions(-) diff --git a/Doc/glossary.rst b/Doc/glossary.rst --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -783,6 +783,14 @@ mapping rather than a sequence because the lookups use arbitrary :term:`immutable` keys rather than integers. + The :class:`collections.abc.Sequence` abstract base class + defines a much richer interface that goes beyond just + :meth:`__getitem__` and :meth:`__len__`, adding :meth:`count`, + :meth:`index`, :meth:`__contains__`, and + :meth:`__reversed__`. Types that implement this expanded + interface can be registered explicitly using + :func:`~abc.register`. + single dispatch A form of :term:`generic function` dispatch where the implementation is chosen based on the type of a single argument. diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst --- a/Doc/library/ipaddress.rst +++ b/Doc/library/ipaddress.rst @@ -167,7 +167,7 @@ .. attribute:: is_unspecified - ``True`` if the address is unspecified. See :RFC:`5375` (for IPv4) + ``True`` if the address is unspecified. See :RFC:`5735` (for IPv4) or :RFC:`2373` (for IPv6). .. attribute:: is_reserved -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 04:44:49 2014 From: python-checkins at python.org (nick.coghlan) Date: Sun, 16 Feb 2014 04:44:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_462_updates=2C_include_Rh?= =?utf-8?q?odeCode_idea?= Message-ID: <3fRZ2n0QTCz7LjN@mail.python.org> http://hg.python.org/peps/rev/ef8d4e914766 changeset: 5372:ef8d4e914766 user: Nick Coghlan date: Sun Feb 16 13:44:37 2014 +1000 summary: PEP 462 updates, include RhodeCode idea files: pep-0462.txt | 281 ++++++++++++++++++++++++++++++++++---- 1 files changed, 245 insertions(+), 36 deletions(-) diff --git a/pep-0462.txt b/pep-0462.txt --- a/pep-0462.txt +++ b/pep-0462.txt @@ -14,16 +14,21 @@ ======== This PEP proposes investing in automation of several of the tedious, time -consuming activities that are currently required for the core developerment +consuming activities that are currently required for the core development team to incorporate changes into CPython. This proposal is intended to allow core developers to make more effective use of the time they have available to contribute to CPython, which should also result in an improved experience for other contributors that are reliant on the core team to get their changes incorporated. +This PEP also proposes changes to the way certain supporting repositories +(such as the repository for Python Enhancement Proposals) are managed to +make them more accessible to new contributors, and easier to manage for +core developers. -Rationale -========= + +Rationale for changes to the core development workflow +====================================================== The current core developer workflow to merge a new feature into CPython on a POSIX system "works" as follows: @@ -114,7 +119,7 @@ afterwards. There are also many, many opportunities for core developers to make -mistakes that inconvience others, both in managing the Mercurial branches +mistakes that inconvenience others, both in managing the Mercurial branches and in breaking the buildbots without being in a position to fix them promptly. This both makes the existing core development team cautious in granting new developers commit access, as well as making those new @@ -139,7 +144,9 @@ managers (since they may need to enlist assistance cleaning up test failures prior to a release) and for the developers themselves (since it creates significant pressure to fix any failures we inadvertently - introduce right *now*, rather than at a more convenient time). + introduce right *now*, rather than at a more convenient time, as well + as potentially making ``hg bisect`` more difficult to use if + ``hg annotate`` isn't sufficient to identify the source of a new failure). * For other contributors, a core developer spending time actually getting changes merged is a developer that isn't reviewing and discussing patches on the issue tracker or otherwise helping others to contribute effectively. @@ -151,6 +158,23 @@ the case for OpenStack). +Rationale for changes to source code repository management +========================================================== + +Currently, hg.python.org hosts more than just the core CPython repository, +it also hosts other repositories such as those for the CPython developer +guide and for Python Enhancement Proposals, along with various "sandbox" +repositories for core developer experimentation. + +These supporting repositories could benefit greatly from user the simple +"pull request" style workflow made popular by code hosting sites like +GitHub and BitBucket. + +This PEP proposes introducing a more sophisticated approach to repository +management that includes more "self service" features, including support +for pull requests. + + Current Tools ============= @@ -162,23 +186,66 @@ * Rietveld (also hosted on bugs.python.org) for code review * Buildbot (buildbot.python.org) for automated testing -This proposal does *not* suggest replacing any of these tools, although -implementing it effectively may require modifications to some or all of -them. +This proposal does *not* currently suggest replacing any of these tools, +although implementing it effectively may require modifications to some or +all of them. It does however suggest the addition of new tools in order to automate -additional parts of the workflow. +additional parts of the workflow, as well as a critical review of these +tools to see which, if any, may be candidates for replacement. Proposal ======== -The essence of this proposal is that CPython aim to adopt a "core reviewer" -development model, similar to that used by the OpenStack project. +This proposal consists of two key components: -These problems experienced by CPython are not unique. The OpenStack -infrastructure team have come up with a well designed automated workflow -that is designed to ensure: +* Introducing RhodeCode for improved repository management +* Introducing automated merge gating for the CPython project + + +Improved repository management +------------------------------ + +The rise of free source code hosting sites like GitHub and BitBucket with a +focus on improving the user experience have increased user expectations +for the web based interface offered for source code repositories. This +includes features like dynamic control of user permissions for repository +administrators, online editing for documentation updates and similar small +fixes, easy cloning and branching, etc. + +While GitHub and BitBucket are proprietary solutions to this problem that +cannot be self-hosted, RhodeCode_ is a popular primarily open source solution +that offers similar features to the major free hosting sites, while also +allowing installation on your own servers. RhodeCode is also implemented +in Python, allowing us to preserve our current situation of having our +workflow tools being almost entirely self-hosting. + +There's nothing too complicated with this part of the proposal: it is +essentially just a suggestion to convert hg.python.org to being backed +by a RhodeCode Enterprise instance hosted on PSF infrastructure. + +All of the functional parts of RhodeCode Enterprise are open source under +the GPLv3 license. The "look & feel" components are licensed under a +`business source license`_ that is free for up to 20 users, as well as for +organisations that qualify for one of RhodeCode's exemption categories +(in the case of ``hg.python.org``, the relevant category is "public open +source project"). + +.. _RhodeCode: https://rhodecode.com/ +.. _business source license: https://rhodecode.com/licenses + + +Automated merge gating for CPython +---------------------------------- + +The essence of this part of the proposal is that CPython aim to adopt a +"core reviewer" development model, similar to that used by the OpenStack +project. + +The workflow problems experienced by the CPython core development team are +not unique. The OpenStack infrastructure team have come up with a well +designed automated workflow that is designed to ensure: * once a patch has been reviewed, further developer involvement is needed only if the automated tests fail prior to merging @@ -187,27 +254,35 @@ * the main development branch always stays green. Patches that do not pass the automated tests do not get merged. +If a core developer wants to tweak a patch prior to merging, they download +it from the review tool, modify and *upload it back to the review tool* +rather than pushing it directly to the source code repository. + The core of this workflow is implemented using a tool called Zuul_, a Python web service created specifically for the OpenStack project, but deliberately designed with a plugin based trigger and action system to make it easier to adapt to alternate code review systems, issue trackers and CI systems. James Blair of the OpenStack infrastructure team provided an `excellent overview of Zuul -`__ at linux.conf.au 2014. +`__ at linux.conf.au 2014. While Zuul handles several workflows for OpenStack, the specific one of interest for this PEP is the "merge gating" workflow. For this workflow, Zuul is configured to monitor the Gerrit code review -system for patches which have been marked as "+2 Approved". Once it sees +system for patches which have been marked as "Approved". Once it sees such a patch, Zuul takes it, and combines it into a queue of "candidate merges". It then creates a pipeline of test runs that execute in parallel in Jenkins (in order to allow more than 24 commits a day when a full test run takes the better part of an hour), and are merged as they pass (and as all the candidate merges ahead of them in the queue pass). If a patch fails the -tests, Zuul takes it of the queue, cancels any test runs after that patch in +tests, Zuul takes it out of the queue, cancels any test runs after that patch in the queue, and rebuilds the queue without the failing patch. +If a developer looks at a test which failed on merge and determines that it +was due to an intermittent failure, then they can resubmit the patch for +another attempt at merging. + To adapt this process to CPython, it should be feasible to have Zuul monitor Rietveld for approved patches (which would require a feature addition in Rietveld), submit them to Buildbot for testing on the stable buildbots, and @@ -225,7 +300,7 @@ directly address several of the issues described in the Rationale above. .. _Zuul: http://ci.openstack.org/zuul/ -.. _Elastic recheck: http://status.openstack.org/elastic-recheck/ +.. _Elastic recheck: http://status.openstack.org/elastic-recheck/> Deferred Proposals @@ -246,9 +321,9 @@ Infrastructure team), I don't see them as offering quite the same kind of fundamental workflow improvement that merge gating appears to provide. -However, it may be that the last is needed to handle intermittent test -failures in the gate effectively, in which case it may need to be -considered as a possible part of the initial deployment. +However, if we find we are having too many problems with intermittent test +failures in the gate, then introducing the "Elastic recheck" feature may +need to be considered as part of the initial deployment. Suggested Variants @@ -269,10 +344,38 @@ deployment proves to have more trouble with test reliability than is anticipated. +It would also be possible to tweak the merge gating criteria such that it doesn't +run the test suite if it detects that the patch hasn't modified any files +outside the "Docs" tree, and instead only checks that the documentation +builds without errors. + +As yet another alternative, it may be reasonable to move some parts of the +documentation (such as the tutorial) out of the main source repository and +manage them using the simpler pull request based model. + Perceived Benefits ================== +Improved repository management +------------------------------ + +The primary benefit of using RhodeCode to manage hg.python.org is that +supporting repositories such as the developer guide and the PEP repo could +now be managed using pull requests and online editing. This would be +much simpler then the current workflow which requires PEP editors and +other core developers to act as intermediaries to apply updates suggested +by other users. + +The richer administrative functionality would also make it substantially +easier to grant users access to particular repositories for collaboration +purposes, without having to grant them general access to the entire +installation. + + +Automated merge gating for CPython +---------------------------------- + The benefits of this proposal accrue most directly to the core development team. First and foremost, it means that once we mark a patch as "Approved" in the updated code review system, *we're usually done*. The extra 20-30 @@ -292,7 +395,7 @@ However, removing this time sink from the core development team should also improve the experience of CPython development for other contributors, as it -removes several of the opportunities for patches to get "dropped on the +eliminates several of the opportunities for patches to get "dropped on the floor", as well as increasing the time core developers are likely to have available for reviewing contributed patches. @@ -324,6 +427,25 @@ Zuul trigger and action plugins, and may require additional development in some of our existing tools. +RhodeCode may also require some adjustment to fit in with existing +infrastructure. + + +User account management +----------------------- + +Ideally, RhodeCode's user account management would be integrated with +the existing account management in Roundup. + + +Preserving existing SSH access and links for Mercurial repositories +------------------------------------------------------------------- + +Adopting RhodeCode may result in some changes to where repositories are +located on the hg.python.org filesystem. We may want to ensure that +existing links into the hg.python.org web service are preserved, and should +definitely ensure that existing SSH based clones continue to work correctly. + Rietveld/Roundup vs Gerrit -------------------------- @@ -379,6 +501,9 @@ such that the hg-git plugin appears to be the most mature of the available options for hg-git interoperability). +One advantage of adopting RhodeCode to manage the repository infrastructure +is that it supports git repositories in addition to Mercurial repositories. + Buildbot vs Jenkins ------------------- @@ -435,15 +560,24 @@ queue. This would just require a change in Rietveld to indicate which branch was the intended target of the patch. -The Python 3.x maintenance branches are potentially more complicated. One -option would be to simply stop using Mercurial merges to manage them, and -instead treat them as independent heads, similar to the Python 2.7 branch. -Patches that applied cleanly to both the active maintenance branch and to -default would then just be submitted to both queues, while other changes -might involve submitting separate patches for the active maintenance branch -and for default. This approach also has the benefit of adjusting cleanly to -the intermittent periods where we have two active Python 3 maintenance -branches. +The Python 3.x maintenance branches are potentially more complicated. My +current recommendation is to simply stop using Mercurial merges to manage +them, and instead treat them as independent heads, similar to the Python +2.7 branch. Patches that apply cleanly to both the active maintenance branch +and to default would then just be submitted to both queues, while other +changes might involve submitting separate patches for the active maintenance +branch and for default. This approach also has the benefit of adjusting +cleanly to the intermittent periods where we have two active Python 3 +maintenance branches. + +This does suggest some user interface ideas for the branch nomination +interface for a patch: + +* default to "default" on issues that are marked as "enhancement" +* default to "3.x+" (where 3.x is the oldest branch in regular maintenance) + on any other issues +* also offer the ability to select specific branches in addition to or + instead of the default selection Handling of security branches @@ -451,13 +585,13 @@ For simplicity's sake, I would suggest leaving the handling of security-fix only branches alone: the release managers for those branches -backport specific changes manually. +would continue to backport specific changes manually. Handling of NEWS file updates ----------------------------- -Our current approaching to handling NEWS file updates regularly results in +Our current approach to handling NEWS file updates regularly results in spurious conflicts when merging bug fixes forward from an active maintenance branch to a later branch. @@ -547,12 +681,87 @@ more automated preparation of release artefacts as well. +Practical Challenges +==================== + +The PSF runs its own directly and indirectly sponsored workflow +infrastructure primarily due to past experience with unacceptably poor +performance and inflexibility of infrastructure provided for free to the +general public. CPython development was originally hosted on SourceForge, +with source control moved to self hosting when SF was both slow to offer +Subversion support and suffering from CVS performance issues (see PEP 347), +while issue tracking later moved to the open source Roundup issue tracker +on dedicated sponsored hosting (from Upfront Systems), due to a combination +of both SF performance issues and general usability issues with the SF +tracker at the time (the outcome and process for the new tracker selection +were captured on the `python.org wiki +`__ rather than in a PEP). + +Accordingly, proposals that involve setting ourselves up for "SourceForge +usability and reliability issues, round two" aren't likely to gain any +traction with either the CPython core development team or with the PSF +Infrastructure committee. This proposal respects that history by +recommending only tools that are available for self-hosting as sponsored +or PSF funded infrastructure, and are also open source Python projects that +can be customised to meet the needs of the CPython core development team. + +However, for this proposal to be a success (if it is accepted), we need to +understand how we are going to carry out the necessary configuration, +customisation, integration and deployment work. + +The last attempt at adding a new piece to the CPython support infrastructure +(speed.python.org) has unfortunately foundered due to the lack of time to +drive the project from the core developers and PSF board members involved, +and the difficulties of trying to bring someone else up to speed to lead +the activity (the hardware donated to that project by HP is currently in +use to support PyPy instead, but the situation highlights some +of the challenges of relying on volunteer labour with many other higher +priority demands on their time to steer projects to completion). + +Even ultimately successful past projects, such as the source control +migrations from CVS to Subversion and from Subversion to Mercurial, the +issue tracker migration from SourceForge to Roundup, the code review +integration between Roundup and Rietveld and the introduction of the +Buildbot continuous integration fleet, have taken an extended period of +time as volunteers worked their way through the many technical and social +challenges involved. + +Accordingly, one possible outcome of this proposal may be a recommendation +to the PSF to investigate how to sustain direct investment in ongoing paid +development on CPython workflow tools, similar to the ongoing funded +development that supports the continuous integration infrastructure for +OpenStack. Some possible approaches include: + +* the PSF funding part-time or contract based development on CPython workflow + tools, either on an ad hoc basic through the existing grants program, or + on a more permanent basis, collaborating with the CPython core development + team to determine the scope of the desired improvements. +* discussing a possible partnership with the OpenStack Foundation to + collaborate on shared tool development that ultimately benefits both + organisations (for example, the OpenStack infrastructure team aren't + especially happy with the maintainability challenges posed by Gerrit, so + improvements to Rietveld to make it a viable candidate for replacing + Gerrit may be something they would be interested in). +* PSF (and OpenStack) sponsor members allocating part-time or full-time + staff to work on improving the CPython workflow tools, similar to the way + such staff are allocated to improving OpenStack workflow tools. + +Note that this model of directing paid development efforts at improving the +tools that support the contributions of volunteers is also one of the +known ways to incorporate funded development into a primarily volunteer +driven project without creating resentment between unpaid and paid +contributors: it's harder to resent people that are being paid specifically +to make the tools, workflow and general experience more pleasant for the +unpaid contributors. + + Open Questions ============== -Pretty much everything in the PEP. Do we want to do this? Is Rietveld the -right place to hook Zuul into our current workflows? How do we want to -address the various technical challenges? +Pretty much everything in the PEP. Do we want to adopt RhodeCode? Do we +want to adopt merge gating and Zuul? Is Rietveld the right place to hook +Zuul into our current workflows? How do we want to address the various +technical challenges? Assuming we do want to do it (or something like it), how is the work going to get done? Do we try to get it done solely as a volunteer effort? Do we -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Feb 16 08:47:34 2014 From: python-checkins at python.org (ezio.melotti) Date: Sun, 16 Feb 2014 08:47:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_broken_link=2E?= Message-ID: <3fRgQt1wD2z7LjR@mail.python.org> http://hg.python.org/peps/rev/c8aa81f9d332 changeset: 5373:c8aa81f9d332 user: Ezio Melotti date: Sun Feb 16 09:47:22 2014 +0200 summary: Fix broken link. files: pep-0462.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0462.txt b/pep-0462.txt --- a/pep-0462.txt +++ b/pep-0462.txt @@ -300,7 +300,7 @@ directly address several of the issues described in the Rationale above. .. _Zuul: http://ci.openstack.org/zuul/ -.. _Elastic recheck: http://status.openstack.org/elastic-recheck/> +.. _Elastic recheck: http://status.openstack.org/elastic-recheck/ Deferred Proposals -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Sun Feb 16 09:33:56 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 16 Feb 2014 09:33:56 +0100 Subject: [Python-checkins] Daily reference leaks (2d62ee3c7617): sum=4 Message-ID: results for 2d62ee3c7617 on branch "default" -------------------------------------------- test_site leaked [0, 0, 2] references, sum=2 test_site leaked [0, 0, 2] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogujYk2F', '-x'] From python-checkins at python.org Sun Feb 16 09:46:11 2014 From: python-checkins at python.org (georg.brandl) Date: Sun, 16 Feb 2014 09:46:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Doc=3A_do_not_rely_on_chec?= =?utf-8?q?ked-out_Sphinx_toolchain_from_svn=2Epython=2Eorg_anymore?= Message-ID: <3fRhkW2rDjz7LmY@mail.python.org> http://hg.python.org/cpython/rev/eef7899ea7ab changeset: 89212:eef7899ea7ab user: Georg Brandl date: Sun Feb 16 09:46:36 2014 +0100 summary: Doc: do not rely on checked-out Sphinx toolchain from svn.python.org anymore Nowadays it is likely that people will have Sphinx installed, and if not, they will know how to install it. This also simplifies life a lot for distribution packagers, who typically do not want the doc build process to connect to external web resources. files: .hgignore | 5 --- Doc/Makefile | 31 +----------------- Doc/conf.py | 2 + Doc/make.bat | 19 ----------- Doc/tools/sphinxext/pyspecific.py | 22 ++++++------ 5 files changed, 15 insertions(+), 64 deletions(-) diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -24,11 +24,6 @@ reflog.txt$ tags$ Lib/plat-mac/errors.rsrc.df.rsrc -Doc/tools/sphinx/ -Doc/tools/docutils/ -Doc/tools/jinja/ -Doc/tools/jinja2/ -Doc/tools/pygments/ Misc/python.pc Misc/python-config.sh$ Modules/Setup$ diff --git a/Doc/Makefile b/Doc/Makefile --- a/Doc/Makefile +++ b/Doc/Makefile @@ -5,7 +5,7 @@ # You can set these variables from the command line. PYTHON = python -SVNROOT = http://svn.python.org/projects +SPHINXBUILD = sphinx-build SPHINXOPTS = PAPER = SOURCES = @@ -21,7 +21,6 @@ help: @echo "Please use \`make ' where is one of" @echo " clean to remove build files" - @echo " update to update build tools" @echo " html to make standalone HTML files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @@ -37,30 +36,8 @@ @echo " check to run a check for frequent markup errors" @echo " serve to serve the documentation on the localhost (8000)" -# Note: if you update versions here, do the same in make.bat and README.txt -checkout: - @if [ ! -d tools/sphinx ]; then \ - echo "Checking out Sphinx..."; \ - svn checkout $(SVNROOT)/external/Sphinx-1.2/sphinx tools/sphinx; \ - fi - @if [ ! -d tools/docutils ]; then \ - echo "Checking out Docutils..."; \ - svn checkout $(SVNROOT)/external/docutils-0.11/docutils tools/docutils; \ - fi - @if [ ! -d tools/jinja2 ]; then \ - echo "Checking out Jinja..."; \ - svn checkout $(SVNROOT)/external/Jinja-2.3.1/jinja2 tools/jinja2; \ - fi - @if [ ! -d tools/pygments ]; then \ - echo "Checking out Pygments..."; \ - svn checkout $(SVNROOT)/external/Pygments-1.6/pygments tools/pygments; \ - fi - -update: clean checkout - build: checkout - mkdir -p build/$(BUILDER) build/doctrees - $(PYTHON) tools/sphinx-build.py $(ALLSPHINXOPTS) + $(SPHINXBUILD) $(ALLSPHINXOPTS) @echo html: BUILDER = html @@ -120,10 +97,6 @@ clean: -rm -rf build/* - -rm -rf tools/sphinx - -rm -rf tools/pygments - -rm -rf tools/jinja2 - -rm -rf tools/docutils dist: rm -rf dist diff --git a/Doc/conf.py b/Doc/conf.py --- a/Doc/conf.py +++ b/Doc/conf.py @@ -61,6 +61,8 @@ # By default, highlight as Python 3. highlight_language = 'python3' +needs_sphinx = '1.1' + # Options for HTML output # ----------------------- diff --git a/Doc/make.bat b/Doc/make.bat --- a/Doc/make.bat +++ b/Doc/make.bat @@ -1,7 +1,6 @@ @@echo off setlocal -set SVNROOT=http://svn.python.org/projects if "%PYTHON%" EQU "" set PYTHON=py -2 if "%HTMLHELP%" EQU "" set HTMLHELP=%ProgramFiles%\HTML Help Workshop\hhc.exe if "%DISTVERSION%" EQU "" for /f "usebackq" %%v in (`%PYTHON% tools/sphinxext/patchlevel.py`) do set DISTVERSION=%%v @@ -14,15 +13,11 @@ if "%1" EQU "suspicious" goto build if "%1" EQU "linkcheck" goto build if "%1" EQU "changes" goto build -if "%1" EQU "checkout" goto checkout -if "%1" EQU "update" goto update :help set this=%~n0 echo HELP echo. -echo %this% checkout -echo %this% update echo %this% html echo %this% htmlhelp echo %this% latex @@ -33,20 +28,6 @@ echo. goto end -:checkout -svn co %SVNROOT%/external/Sphinx-1.2/sphinx tools/sphinx -svn co %SVNROOT%/external/docutils-0.11/docutils tools/docutils -svn co %SVNROOT%/external/Jinja-2.3.1/jinja2 tools/jinja2 -svn co %SVNROOT%/external/Pygments-1.6/pygments tools/pygments -goto end - -:update -svn update tools/sphinx -svn update tools/docutils -svn update tools/jinja2 -svn update tools/pygments -goto end - :build if not exist build mkdir build if not exist build\%1 mkdir build\%1 diff --git a/Doc/tools/sphinxext/pyspecific.py b/Doc/tools/sphinxext/pyspecific.py --- a/Doc/tools/sphinxext/pyspecific.py +++ b/Doc/tools/sphinxext/pyspecific.py @@ -16,6 +16,7 @@ import sphinx from sphinx.util.nodes import split_explicit_title +from sphinx.util.compat import Directive from sphinx.writers.html import HTMLTranslator from sphinx.writers.latex import LaTeXTranslator from sphinx.locale import versionlabels @@ -27,7 +28,9 @@ Body.enum.converters['lowerroman'] = \ Body.enum.converters['upperroman'] = lambda x: None -if sphinx.__version__[:3] < '1.2': +SPHINX11 = sphinx.__version__[:3] < '1.2' + +if SPHINX11: # monkey-patch HTML translator to give versionmodified paragraphs a class def new_visit_versionmodified(self, node): self.body.append(self.starttag(node, 'p', CLASS=node['type'])) @@ -88,8 +91,6 @@ # Support for marking up implementation details -from sphinx.util.compat import Directive - class ImplementationDetail(Directive): has_content = True @@ -142,10 +143,6 @@ # Support for documenting version of removal in deprecations -from sphinx.locale import versionlabels -from sphinx.util.compat import Directive - - class DeprecatedRemoved(Directive): has_content = True required_arguments = 2 @@ -171,16 +168,16 @@ messages = [] if self.content: self.state.nested_parse(self.content, self.content_offset, node) - if len(node): if isinstance(node[0], nodes.paragraph) and node[0].rawsource: content = nodes.inline(node[0].rawsource, translatable=True) content.source = node[0].source content.line = node[0].line content += node[0].children node[0].replace_self(nodes.paragraph('', '', content)) - node[0].insert(0, nodes.inline('', '%s: ' % text, - classes=['versionmodified'])) - else: + if not SPHINX11: + node[0].insert(0, nodes.inline('', '%s: ' % text, + classes=['versionmodified'])) + elif not SPHINX11: para = nodes.paragraph('', '', nodes.inline('', '%s.' % text, classes=['versionmodified'])) node.append(para) @@ -188,6 +185,9 @@ env.note_versionchange('deprecated', version[0], node, self.lineno) return [node] + messages +# for Sphinx < 1.2 +versionlabels['deprecated-removed'] = DeprecatedRemoved._label + # Support for including Misc/NEWS -- Repository URL: http://hg.python.org/cpython From tjreedy at udel.edu Sun Feb 16 11:05:34 2014 From: tjreedy at udel.edu (Terry Reedy) Date: Sun, 16 Feb 2014 05:05:34 -0500 Subject: [Python-checkins] cpython: Doc: do not rely on checked-out Sphinx toolchain from svn.python.org anymore In-Reply-To: <3fRhkW2rDjz7LmY@mail.python.org> References: <3fRhkW2rDjz7LmY@mail.python.org> Message-ID: <53008D6E.3060605@udel.edu> On 2/16/2014 3:46 AM, georg.brandl wrote: > http://hg.python.org/cpython/rev/eef7899ea7ab > changeset: 89212:eef7899ea7ab > user: Georg Brandl > date: Sun Feb 16 09:46:36 2014 +0100 > summary: > Doc: do not rely on checked-out Sphinx toolchain from svn.python.org anymore For me, working on Windows, this patch is a regression. I somehow missed the discussion, and I do not see an issue number. > Nowadays it is likely that people will have Sphinx installed, I have Sphinx installed because make(.bat) checkout installed it. I suspect that most people setting up on Windows will not have it already. > and if not, they will know how to install it. Sorry, I don't. Make checkout installed 4 packages, so it looks like there are 4 installs. These have to not only be installed, but installed so that the rest of make.bat still works, or perhaps make.bat will have to be revised. > This also simplifies life a lot for distribution packagers, > who typically do not want the doc build process to connect > to external web resources. This is irrelevant for a repository on Windows. If the files are still on svn.python.org, why disable something that works? If they have been removed, please provide substitute instructions, if not a .bat file, that have been tested and shown to work on Windows Terry From python-checkins at python.org Sun Feb 16 17:14:17 2014 From: python-checkins at python.org (andrew.kuchling) Date: Sun, 16 Feb 2014 17:14:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzEyMjExOiBjbGFy?= =?utf-8?q?ify_math=2Ecopysign=28=29_documentation_and_docstring?= Message-ID: <3fRtgY3zyVz7LjT@mail.python.org> http://hg.python.org/cpython/rev/3ad7725b5013 changeset: 89213:3ad7725b5013 branch: 3.3 parent: 89210:383f4eede628 user: Andrew Kuchling date: Sun Feb 16 11:11:25 2014 -0500 summary: #12211: clarify math.copysign() documentation and docstring files: Doc/library/math.rst | 7 +++++-- Modules/mathmodule.c | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -36,9 +36,12 @@ .. function:: copysign(x, y) - Return *x* with the sign of *y*. On a platform that supports - signed zeros, ``copysign(1.0, -0.0)`` returns *-1.0*. + Return a float with the magnitude (absolute value) of *x* but the sign of + *y*. On platforms that support signed zeros, ``copysign(1.0, -0.0)`` + returns *-1.0*. + If *x* is NaN, *y* is ignored and NaN is returned. If *y* is NaN, + it is treated as positive: ``copysign(-1.0, NaN)`` returns 1.0. .. function:: fabs(x) diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -906,7 +906,11 @@ "This is the smallest integral value >= x."); FUNC2(copysign, copysign, - "copysign(x, y)\n\nReturn x with the sign of y.") + "copysign(x, y)\n\nReturn a float with the magnitude (absolute value) " + "of x but the sign \nof y. On platforms that support signed zeros, " + "copysign(1.0, -0.0) \nreturns -1.0.\n\n" + "If x is NaN, y is ignored and NaN is returned. If y is NaN, it is\n" + "treated as positive.") FUNC1(cos, cos, 0, "cos(x)\n\nReturn the cosine of x (measured in radians).") FUNC1(cosh, cosh, 1, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 17:15:20 2014 From: python-checkins at python.org (andrew.kuchling) Date: Sun, 16 Feb 2014 17:15:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E3?= Message-ID: <3fRthm70jjz7Lk7@mail.python.org> http://hg.python.org/cpython/rev/7d54853d2b72 changeset: 89214:7d54853d2b72 parent: 89212:eef7899ea7ab parent: 89213:3ad7725b5013 user: Andrew Kuchling date: Sun Feb 16 11:15:13 2014 -0500 summary: Merge from 3.3 files: Doc/library/math.rst | 7 +++++-- Modules/mathmodule.c | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -36,9 +36,12 @@ .. function:: copysign(x, y) - Return *x* with the sign of *y*. On a platform that supports - signed zeros, ``copysign(1.0, -0.0)`` returns *-1.0*. + Return a float with the magnitude (absolute value) of *x* but the sign of + *y*. On platforms that support signed zeros, ``copysign(1.0, -0.0)`` + returns *-1.0*. + If *x* is NaN, *y* is ignored and NaN is returned. If *y* is NaN, + it is treated as positive: ``copysign(-1.0, NaN)`` returns 1.0. .. function:: fabs(x) diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -906,7 +906,11 @@ "This is the smallest integral value >= x."); FUNC2(copysign, copysign, - "copysign(x, y)\n\nReturn x with the sign of y.") + "copysign(x, y)\n\nReturn a float with the magnitude (absolute value) " + "of x but the sign \nof y. On platforms that support signed zeros, " + "copysign(1.0, -0.0) \nreturns -1.0.\n\n" + "If x is NaN, y is ignored and NaN is returned. If y is NaN, it is\n" + "treated as positive.") FUNC1(cos, cos, 0, "cos(x)\n\nReturn the cosine of x (measured in radians).") FUNC1(cosh, cosh, 1, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 18:11:03 2014 From: python-checkins at python.org (andrew.kuchling) Date: Sun, 16 Feb 2014 18:11:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzEyMjExOiByZW1v?= =?utf-8?q?ve_paragraph_about_NaNs?= Message-ID: <3fRvx35v31z7LjN@mail.python.org> http://hg.python.org/cpython/rev/b01f4ed077fa changeset: 89215:b01f4ed077fa branch: 3.3 parent: 89213:3ad7725b5013 user: Andrew Kuchling date: Sun Feb 16 12:09:35 2014 -0500 summary: #12211: remove paragraph about NaNs files: Doc/library/math.rst | 3 --- Modules/mathmodule.c | 4 +--- 2 files changed, 1 insertions(+), 6 deletions(-) diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -40,9 +40,6 @@ *y*. On platforms that support signed zeros, ``copysign(1.0, -0.0)`` returns *-1.0*. - If *x* is NaN, *y* is ignored and NaN is returned. If *y* is NaN, - it is treated as positive: ``copysign(-1.0, NaN)`` returns 1.0. - .. function:: fabs(x) Return the absolute value of *x*. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -908,9 +908,7 @@ FUNC2(copysign, copysign, "copysign(x, y)\n\nReturn a float with the magnitude (absolute value) " "of x but the sign \nof y. On platforms that support signed zeros, " - "copysign(1.0, -0.0) \nreturns -1.0.\n\n" - "If x is NaN, y is ignored and NaN is returned. If y is NaN, it is\n" - "treated as positive.") + "copysign(1.0, -0.0) \nreturns -1.0.\n") FUNC1(cos, cos, 0, "cos(x)\n\nReturn the cosine of x (measured in radians).") FUNC1(cosh, cosh, 1, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 18:18:29 2014 From: python-checkins at python.org (andrew.kuchling) Date: Sun, 16 Feb 2014 18:18:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E3?= Message-ID: <3fRw5d613dz7LjM@mail.python.org> http://hg.python.org/cpython/rev/635470340cf3 changeset: 89216:635470340cf3 parent: 89214:7d54853d2b72 parent: 89215:b01f4ed077fa user: Andrew Kuchling date: Sun Feb 16 12:18:17 2014 -0500 summary: Merge from 3.3 files: Doc/library/math.rst | 3 --- Modules/mathmodule.c | 4 +--- 2 files changed, 1 insertions(+), 6 deletions(-) diff --git a/Doc/library/math.rst b/Doc/library/math.rst --- a/Doc/library/math.rst +++ b/Doc/library/math.rst @@ -40,9 +40,6 @@ *y*. On platforms that support signed zeros, ``copysign(1.0, -0.0)`` returns *-1.0*. - If *x* is NaN, *y* is ignored and NaN is returned. If *y* is NaN, - it is treated as positive: ``copysign(-1.0, NaN)`` returns 1.0. - .. function:: fabs(x) Return the absolute value of *x*. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -908,9 +908,7 @@ FUNC2(copysign, copysign, "copysign(x, y)\n\nReturn a float with the magnitude (absolute value) " "of x but the sign \nof y. On platforms that support signed zeros, " - "copysign(1.0, -0.0) \nreturns -1.0.\n\n" - "If x is NaN, y is ignored and NaN is returned. If y is NaN, it is\n" - "treated as positive.") + "copysign(1.0, -0.0) \nreturns -1.0.\n") FUNC1(cos, cos, 0, "cos(x)\n\nReturn the cosine of x (measured in radians).") FUNC1(cosh, cosh, 1, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 18:47:01 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 18:47:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_do_not_line_br?= =?utf-8?q?eak_reference?= Message-ID: <3fRwkY6tQcz7LjM@mail.python.org> http://hg.python.org/cpython/rev/4a3f1c1890fa changeset: 89217:4a3f1c1890fa branch: 3.3 parent: 89215:b01f4ed077fa user: Benjamin Peterson date: Sun Feb 16 12:46:30 2014 -0500 summary: do not line break reference files: Doc/library/unittest.rst | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -1755,13 +1755,13 @@ By default this runner shows :exc:`DeprecationWarning`, :exc:`PendingDeprecationWarning`, :exc:`ResourceWarning` and - :exc:`ImportWarning` even if they are :ref:`ignored by default `. Deprecation warnings caused by :ref:`deprecated unittest methods - ` are also special-cased and, when the warning filters - are ``'default'`` or ``'always'``, they will appear only once per-module, in - order to avoid too many warning messages. This behavior can be overridden - using the :option:`-Wd` or :option:`-Wa` options and leaving *warnings* to - ``None``. + :exc:`ImportWarning` even if they are :ref:`ignored by default + `. Deprecation warnings caused by :ref:`deprecated unittest + methods ` are also special-cased and, when the warning + filters are ``'default'`` or ``'always'``, they will appear only once + per-module, in order to avoid too many warning messages. This behavior can + be overridden using the :option:`-Wd` or :option:`-Wa` options and leaving + *warnings* to ``None``. .. versionchanged:: 3.2 Added the ``warnings`` argument. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 18:47:03 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 18:47:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4z?= Message-ID: <3fRwkb1S0Cz7LjM@mail.python.org> http://hg.python.org/cpython/rev/fb5f4cfc3230 changeset: 89218:fb5f4cfc3230 parent: 89216:635470340cf3 parent: 89217:4a3f1c1890fa user: Benjamin Peterson date: Sun Feb 16 12:46:38 2014 -0500 summary: merge 3.3 files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 18:57:38 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 18:57:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_I_suppose_this_might_as_w?= =?utf-8?q?ell_be_a_core_area?= Message-ID: <3fRwyp6Z3fzQKf@mail.python.org> http://hg.python.org/devguide/rev/8bc55563bb27 changeset: 667:8bc55563bb27 user: Benjamin Peterson date: Sun Feb 16 12:57:22 2014 -0500 summary: I suppose this might as well be a core area files: experts.rst | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/experts.rst b/experts.rst --- a/experts.rst +++ b/experts.rst @@ -323,6 +323,7 @@ mathematics mark.dickinson, eric.smith, lemburg, stutzbach memory management tim.peters, lemburg networking giampaolo.rodola, pitrou +object model benjamin.peterson packaging tarek, lemburg, alexis, eric.araujo py3 transition benjamin.peterson release management tarek, lemburg, benjamin.peterson, barry, loewis, -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Feb 16 18:57:40 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 18:57:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_I_like_bytecode?= Message-ID: <3fRwyr1nmsz7LjY@mail.python.org> http://hg.python.org/devguide/rev/a2ff846a3926 changeset: 668:a2ff846a3926 user: Benjamin Peterson date: Sun Feb 16 12:57:34 2014 -0500 summary: I like bytecode files: experts.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/experts.rst b/experts.rst --- a/experts.rst +++ b/experts.rst @@ -307,7 +307,7 @@ benchmarks pitrou, brett.cannon bug tracker ezio.melotti buildbots pitrou -bytecode pitrou, georg.brandl +bytecode benjamin.peterson, pitrou, georg.brandl context managers ncoghlan coverity scan christian.heimes, brett.cannon cryptography christian.heimes, gregory.p.smith -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Feb 16 19:49:30 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 19:49:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_look_up_=5F=5Fgetnewargs?= =?utf-8?b?X18gYW5kIF9fZ2V0bmV3YXJnc19leF9fIG9uIHRoZSBvYmplY3QgdHlwZSAo?= =?utf-8?q?=2316251=29?= Message-ID: <3fRy6f2P7Vz7LjV@mail.python.org> http://hg.python.org/cpython/rev/b328f8ccbccf changeset: 89219:b328f8ccbccf user: Benjamin Peterson date: Sun Feb 16 13:49:16 2014 -0500 summary: look up __getnewargs__ and __getnewargs_ex__ on the object type (#16251) files: Lib/test/test_descr.py | 14 ++++++++++++++ Misc/NEWS | 3 +++ Objects/typeobject.c | 18 ++++++------------ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4701,6 +4701,20 @@ for proto in protocols: self._check_reduce(proto, obj, listitems=list(obj)) + def test_special_method_lookup(self): + protocols = range(pickle.HIGHEST_PROTOCOL + 1) + class Picky: + def __getstate__(self): + return {} + + def __getattr__(self, attr): + if attr in ("__getnewargs__", "__getnewargs_ex__"): + raise AssertionError(attr) + return None + for protocol in protocols: + state = {} if protocol >= 2 else None + self._check_reduce(protocol, Picky(), state=state) + def _assert_is_copy(self, obj, objcopy, msg=None): """Utility method to verify if two objects are copies of each others. """ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #20261: In pickle, lookup __getnewargs__ and __getnewargs_ex__ on the + type of the object. + - Issue #20619: Give the AST nodes of keyword-only arguments a column and line number. diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3719,7 +3719,7 @@ /* We first attempt to fetch the arguments for __new__ by calling __getnewargs_ex__ on the object. */ - getnewargs_ex = _PyObject_GetAttrId(obj, &PyId___getnewargs_ex__); + getnewargs_ex = _PyObject_LookupSpecial(obj, &PyId___getnewargs_ex__); if (getnewargs_ex != NULL) { PyObject *newargs = PyObject_CallObject(getnewargs_ex, NULL); Py_DECREF(getnewargs_ex); @@ -3766,16 +3766,13 @@ return -1; } return 0; - } else { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { - return -1; - } - PyErr_Clear(); + } else if (PyErr_Occurred()) { + return -1; } /* The object does not have __getnewargs_ex__ so we fallback on using __getnewargs__ instead. */ - getnewargs = _PyObject_GetAttrId(obj, &PyId___getnewargs__); + getnewargs = _PyObject_LookupSpecial(obj, &PyId___getnewargs__); if (getnewargs != NULL) { *args = PyObject_CallObject(getnewargs, NULL); Py_DECREF(getnewargs); @@ -3791,11 +3788,8 @@ } *kwargs = NULL; return 0; - } else { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { - return -1; - } - PyErr_Clear(); + } else if (PyErr_Occurred()) { + return -1; } /* The object does not have __getnewargs_ex__ and __getnewargs__. This may -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 20:21:45 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 20:21:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_backout_d28242?= =?utf-8?q?a636c7_so_I_can_backout_2807a5f011e4?= Message-ID: <3fRyqs5BHxz7Ljb@mail.python.org> http://hg.python.org/cpython/rev/0f9acc2365a5 changeset: 89220:0f9acc2365a5 branch: 3.3 parent: 89217:4a3f1c1890fa user: Benjamin Peterson date: Sun Feb 16 14:11:56 2014 -0500 summary: backout d28242a636c7 so I can backout 2807a5f011e4 files: Modules/zipimport.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Modules/zipimport.c b/Modules/zipimport.c --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -958,8 +958,10 @@ } Py_XDECREF(self->files); /* free the old value. */ self->files = files; + } else { + /* No problem, discard the new stat data. */ + Py_DECREF(stat_now); } - Py_DECREF(stat_now); } /* stat succeeded */ return fp; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 20:21:47 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 20:21:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_backout_2807a5?= =?utf-8?q?f011e4_for_causing_=2320621?= Message-ID: <3fRyqv1Y9Jz7LkH@mail.python.org> http://hg.python.org/cpython/rev/5330de5c9d2d changeset: 89221:5330de5c9d2d branch: 3.3 user: Benjamin Peterson date: Sun Feb 16 14:12:57 2014 -0500 summary: backout 2807a5f011e4 for causing #20621 files: Lib/test/test_zipimport.py | 104 +------- Modules/zipimport.c | 287 ++++-------------------- 2 files changed, 67 insertions(+), 324 deletions(-) diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -46,27 +46,6 @@ pyc_ext = ('.pyc' if __debug__ else '.pyo') -def _write_zip_package(zipname, files, - data_to_prepend=b"", compression=ZIP_STORED): - z = ZipFile(zipname, "w") - try: - for name, (mtime, data) in files.items(): - zinfo = ZipInfo(name, time.localtime(mtime)) - zinfo.compress_type = compression - z.writestr(zinfo, data) - finally: - z.close() - - if data_to_prepend: - # Prepend data to the start of the zipfile - with open(zipname, "rb") as f: - zip_data = f.read() - - with open(zipname, "wb") as f: - f.write(data_to_prepend) - f.write(zip_data) - - class UncompressedZipImportTestCase(ImportHooksBaseTestCase): compression = ZIP_STORED @@ -79,9 +58,23 @@ ImportHooksBaseTestCase.setUp(self) def doTest(self, expected_ext, files, *modules, **kw): - _write_zip_package(TEMP_ZIP, files, data_to_prepend=kw.get("stuff"), - compression=self.compression) + z = ZipFile(TEMP_ZIP, "w") try: + for name, (mtime, data) in files.items(): + zinfo = ZipInfo(name, time.localtime(mtime)) + zinfo.compress_type = self.compression + z.writestr(zinfo, data) + z.close() + + stuff = kw.get("stuff", None) + if stuff is not None: + # Prepend 'stuff' to the start of the zipfile + with open(TEMP_ZIP, "rb") as f: + data = f.read() + with open(TEMP_ZIP, "wb") as f: + f.write(stuff) + f.write(data) + sys.path.insert(0, TEMP_ZIP) mod = __import__(".".join(modules), globals(), locals(), @@ -96,8 +89,7 @@ self.assertEqual(file, os.path.join(TEMP_ZIP, *modules) + expected_ext) finally: - while TEMP_ZIP in sys.path: - sys.path.remove(TEMP_ZIP) + z.close() os.remove(TEMP_ZIP) def testAFakeZlib(self): @@ -403,67 +395,10 @@ compression = ZIP_DEFLATED -class ZipFileModifiedAfterImportTestCase(ImportHooksBaseTestCase): - def setUp(self): - zipimport._zip_directory_cache.clear() - zipimport._zip_stat_cache.clear() - ImportHooksBaseTestCase.setUp(self) - - def tearDown(self): - ImportHooksBaseTestCase.tearDown(self) - if os.path.exists(TEMP_ZIP): - os.remove(TEMP_ZIP) - - def testZipFileChangesAfterFirstImport(self): - """Alter the zip file after caching its index and try an import.""" - packdir = TESTPACK + os.sep - files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc), - packdir + TESTMOD + ".py": (NOW, "test_value = 38\n"), - "ziptest_a.py": (NOW, "test_value = 23\n"), - "ziptest_b.py": (NOW, "test_value = 42\n"), - "ziptest_c.py": (NOW, "test_value = 1337\n")} - zipfile_path = TEMP_ZIP - _write_zip_package(zipfile_path, files) - self.assertTrue(os.path.exists(zipfile_path)) - sys.path.insert(0, zipfile_path) - - # Import something out of the zipfile and confirm it is correct. - testmod = __import__(TESTPACK + "." + TESTMOD, - globals(), locals(), ["__dummy__"]) - self.assertEqual(testmod.test_value, 38) - # Import something else out of the zipfile and confirm it is correct. - ziptest_b = __import__("ziptest_b", globals(), locals(), ["test_value"]) - self.assertEqual(ziptest_b.test_value, 42) - - # Truncate and fill the zip file with non-zip garbage. - with open(zipfile_path, "rb") as orig_zip_file: - orig_zip_file_contents = orig_zip_file.read() - with open(zipfile_path, "wb") as byebye_valid_zip_file: - byebye_valid_zip_file.write(b"Tear down this wall!\n"*1987) - # Now that the zipfile has been replaced, import something else from it - # which should fail as the file contents are now garbage. - with self.assertRaises(ImportError): - ziptest_a = __import__("ziptest_a", globals(), locals(), - ["test_value"]) - self.assertEqual(ziptest_a.test_value, 23) - - # Now lets make it a valid zipfile that has some garbage at the start. - # This alters all of the offsets within the file - with open(zipfile_path, "wb") as new_zip_file: - new_zip_file.write(b"X"*1991) # The year Python was created. - new_zip_file.write(orig_zip_file_contents) - - # Now that the zip file has been "restored" to a valid but different - # zipfile the zipimporter should *successfully* re-read the new zip - # file's end of file central index and be able to import from it again. - ziptest_c = __import__("ziptest_c", globals(), locals(), ["test_value"]) - self.assertEqual(ziptest_c.test_value, 1337) - - class BadFileZipImportTestCase(unittest.TestCase): def assertZipFailure(self, filename): - with self.assertRaises(zipimport.ZipImportError): - zipimport.zipimporter(filename) + self.assertRaises(zipimport.ZipImportError, + zipimport.zipimporter, filename) def testNoFile(self): self.assertZipFailure('AdfjdkFJKDFJjdklfjs') @@ -537,7 +472,6 @@ UncompressedZipImportTestCase, CompressedZipImportTestCase, BadFileZipImportTestCase, - ZipFileModifiedAfterImportTestCase, ) finally: support.unlink(TESTMOD) diff --git a/Modules/zipimport.c b/Modules/zipimport.c --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -45,16 +45,10 @@ static PyObject *ZipImportError; /* read_directory() cache */ static PyObject *zip_directory_cache = NULL; -static PyObject *zip_stat_cache = NULL; -/* posix.fstat or nt.fstat function. Used due to posixmodule.c's - * superior fstat implementation over libc's on Windows. */ -static PyObject *fstat_function = NULL; /* posix.fstat() or nt.fstat() */ /* forward decls */ -static FILE *fopen_rb_and_stat(PyObject *path, PyObject **py_stat_p); -static FILE *safely_reopen_archive(ZipImporter *self); -static PyObject *read_directory(FILE *fp, PyObject *archive); -static PyObject *get_data(FILE *fp, PyObject *archive, PyObject *toc_entry); +static PyObject *read_directory(PyObject *archive); +static PyObject *get_data(PyObject *archive, PyObject *toc_entry); static PyObject *get_module_code(ZipImporter *self, PyObject *fullname, int *p_ispackage, PyObject **p_modpath); @@ -134,39 +128,11 @@ files = PyDict_GetItem(zip_directory_cache, filename); if (files == NULL) { - PyObject *zip_stat = NULL; - FILE *fp = fopen_rb_and_stat(filename, &zip_stat); - if (fp == NULL) { - if (!PyErr_Occurred()) - PyErr_Format(ZipImportError, "can't open Zip file: %R", - filename); - - Py_XDECREF(zip_stat); + files = read_directory(filename); + if (files == NULL) goto error; - } - - if (Py_VerboseFlag) - PySys_FormatStderr("# zipimport: %U not cached, " - "reading TOC.\n", filename); - - files = read_directory(fp, filename); - fclose(fp); - if (files == NULL) { - Py_XDECREF(zip_stat); + if (PyDict_SetItem(zip_directory_cache, filename, files) != 0) goto error; - } - if (PyDict_SetItem(zip_directory_cache, filename, files) != 0) { - Py_DECREF(files); - Py_XDECREF(zip_stat); - goto error; - } - if (zip_stat && PyDict_SetItem(zip_stat_cache, filename, - zip_stat) != 0) { - Py_DECREF(files); - Py_DECREF(zip_stat); - goto error; - } - Py_XDECREF(zip_stat); } else Py_INCREF(files); @@ -588,11 +554,10 @@ { ZipImporter *self = (ZipImporter *)obj; PyObject *path, *key; - FILE *fp; #ifdef ALTSEP _Py_IDENTIFIER(replace); #endif - PyObject *toc_entry, *data; + PyObject *toc_entry; Py_ssize_t path_start, path_len, len; if (!PyArg_ParseTuple(args, "U:zipimporter.get_data", &path)) @@ -620,23 +585,15 @@ key = PyUnicode_Substring(path, path_start, path_len); if (key == NULL) goto error; - - fp = safely_reopen_archive(self); - if (fp == NULL) - goto error; - toc_entry = PyDict_GetItem(self->files, key); if (toc_entry == NULL) { PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, key); Py_DECREF(key); - fclose(fp); goto error; } Py_DECREF(key); Py_DECREF(path); - data = get_data(fp, self->archive, toc_entry); - fclose(fp); - return data; + return get_data(self->archive, toc_entry); error: Py_DECREF(path); return NULL; @@ -661,7 +618,6 @@ PyObject *toc_entry; PyObject *fullname, *subname, *path, *fullpath; enum zi_module_info mi; - FILE *fp; if (!PyArg_ParseTuple(args, "U:zipimporter.get_source", &fullname)) return NULL; @@ -691,18 +647,11 @@ if (fullpath == NULL) return NULL; - fp = safely_reopen_archive(self); - if (fp == NULL) { - Py_DECREF(fullpath); - return NULL; - } - toc_entry = PyDict_GetItem(self->files, fullpath); Py_DECREF(fullpath); if (toc_entry != NULL) { PyObject *res, *bytes; - bytes = get_data(fp, self->archive, toc_entry); - fclose(fp); + bytes = get_data(self->archive, toc_entry); if (bytes == NULL) return NULL; res = PyUnicode_FromStringAndSize(PyBytes_AS_STRING(bytes), @@ -710,10 +659,10 @@ Py_DECREF(bytes); return res; } - fclose(fp); /* we have the module, but no source */ - Py_RETURN_NONE; + Py_INCREF(Py_None); + return Py_None; } PyDoc_STRVAR(doc_find_module, @@ -879,135 +828,10 @@ return x; } -/* Return 1 if objects a and b fail a Py_EQ test for an attr. */ -static int -compare_obj_attr_strings(PyObject *obj_a, PyObject *obj_b, char *attr_name) -{ - int problem = 0; - PyObject *attr_a = PyObject_GetAttrString(obj_a, attr_name); - PyObject *attr_b = PyObject_GetAttrString(obj_b, attr_name); - if (attr_a == NULL || attr_b == NULL) - problem = 1; - else - problem = (PyObject_RichCompareBool(attr_a, attr_b, Py_EQ) != 1); - Py_XDECREF(attr_a); - Py_XDECREF(attr_b); - return problem; -} +/* + read_directory(archive) -> files dict (new reference) -/* - * Returns an open FILE * on success. - * Returns NULL on error with the Python error context set. - */ -static FILE * -safely_reopen_archive(ZipImporter *self) -{ - FILE *fp; - PyObject *stat_now = NULL; - - fp = fopen_rb_and_stat(self->archive, &stat_now); - if (!fp) { - PyErr_Format(ZipImportError, - "zipimport: can not open file %U", self->archive); - Py_XDECREF(stat_now); - return NULL; - } - - if (stat_now != NULL) { - int problem = 0; - PyObject *files; - PyObject *prev_stat = PyDict_GetItem(zip_stat_cache, self->archive); - /* Test stat_now vs the old cached stat on some key attributes. */ - if (prev_stat != NULL) { - problem = compare_obj_attr_strings(prev_stat, stat_now, - "st_ino"); - problem |= compare_obj_attr_strings(prev_stat, stat_now, - "st_size"); - problem |= compare_obj_attr_strings(prev_stat, stat_now, - "st_mtime"); - } else { - if (Py_VerboseFlag) - PySys_FormatStderr("# zipimport: no stat data for %U!\n", - self->archive); - problem = 1; - } - - if (problem) { - if (Py_VerboseFlag) - PySys_FormatStderr("# zipimport: %U modified since last" - " import, rereading TOC.\n", self->archive); - files = read_directory(fp, self->archive); - if (files == NULL) { - Py_DECREF(stat_now); - fclose(fp); - return NULL; - } - if (PyDict_SetItem(zip_directory_cache, self->archive, - files) != 0) { - Py_DECREF(files); - Py_DECREF(stat_now); - fclose(fp); - return NULL; - } - if (stat_now && PyDict_SetItem(zip_stat_cache, self->archive, - stat_now) != 0) { - Py_DECREF(files); - Py_DECREF(stat_now); - fclose(fp); - return NULL; - } - Py_XDECREF(self->files); /* free the old value. */ - self->files = files; - } else { - /* No problem, discard the new stat data. */ - Py_DECREF(stat_now); - } - } /* stat succeeded */ - - return fp; -} - -/* - fopen_rb_and_stat(path, &py_stat) -> FILE * - - Opens path in "rb" mode and populates the Python py_stat stat_result - with information about the opened file. *py_stat may not be changed - if there is no fstat_function or if fstat_function fails. - - Returns NULL and does nothing to *py_stat if the open failed. -*/ -static FILE * -fopen_rb_and_stat(PyObject *path, PyObject **py_stat_p) -{ - FILE *fp; - assert(py_stat_p != NULL); - assert(*py_stat_p == NULL); - - fp = _Py_fopen(path, "rb"); - if (fp == NULL) { - if (!PyErr_Occurred()) - PyErr_Format(ZipImportError, - "zipimport: can not open file %U", path); - return NULL; - } - - if (fstat_function) { - PyObject *stat_result = PyObject_CallFunction(fstat_function, - "i", fileno(fp)); - if (stat_result == NULL) { - PyErr_Clear(); /* We can function without it. */ - } else { - *py_stat_p = stat_result; - } - } - - return fp; -} - -/* - read_directory(fp, archive) -> files dict (new reference) - - Given an open Zip archive, build a dict, mapping file names + Given a path to a Zip archive, build a dict, mapping file names (local to the archive, using SEP as a separator) to toc entries. A toc_entry is a tuple: @@ -1027,9 +851,10 @@ data_size and file_offset are 0. */ static PyObject * -read_directory(FILE *fp, PyObject *archive) +read_directory(PyObject *archive) { PyObject *files = NULL; + FILE *fp; unsigned short flags; short compress, time, date, name_size; long crc, data_size, file_size, header_size; @@ -1044,18 +869,27 @@ const char *charset; int bootstrap; - assert(fp != NULL); + fp = _Py_fopen(archive, "rb"); + if (fp == NULL) { + if (!PyErr_Occurred()) + PyErr_Format(ZipImportError, "can't open Zip file: %R", archive); + return NULL; + } + if (fseek(fp, -22, SEEK_END) == -1) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } header_position = ftell(fp); if (fread(endof_central_dir, 1, 22, fp) != 22) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) { /* Bad: End of Central Dir signature */ + fclose(fp); PyErr_Format(ZipImportError, "not a Zip file: %R", archive); return NULL; } @@ -1149,16 +983,19 @@ goto error; count++; } + fclose(fp); if (Py_VerboseFlag) PySys_FormatStderr("# zipimport: found %ld names in %R\n", count, archive); return files; fseek_error: + fclose(fp); Py_XDECREF(files); Py_XDECREF(nameobj); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; error: + fclose(fp); Py_XDECREF(files); Py_XDECREF(nameobj); return NULL; @@ -1197,13 +1034,14 @@ return decompress; } -/* Given a FILE* to a Zip file and a toc_entry, return the (uncompressed) +/* Given a path to a Zip file and a toc_entry, return the (uncompressed) data as a new reference. */ static PyObject * -get_data(FILE *fp, PyObject *archive, PyObject *toc_entry) +get_data(PyObject *archive, PyObject *toc_entry) { PyObject *raw_data, *data = NULL, *decompress; char *buf; + FILE *fp; int err; Py_ssize_t bytes_read = 0; long l; @@ -1217,8 +1055,17 @@ return NULL; } + fp = _Py_fopen(archive, "rb"); + if (!fp) { + if (!PyErr_Occurred()) + PyErr_Format(PyExc_IOError, + "zipimport: can not open file %U", archive); + return NULL; + } + /* Check to make sure the local file header is correct */ if (fseek(fp, file_offset, 0) == -1) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } @@ -1229,9 +1076,11 @@ PyErr_Format(ZipImportError, "bad local file header in %U", archive); + fclose(fp); return NULL; } if (fseek(fp, file_offset + 26, 0) == -1) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } @@ -1246,6 +1095,7 @@ raw_data = PyBytes_FromStringAndSize((char *)NULL, bytes_size); if (raw_data == NULL) { + fclose(fp); return NULL; } buf = PyBytes_AsString(raw_data); @@ -1254,9 +1104,11 @@ if (err == 0) { bytes_read = fread(buf, 1, data_size, fp); } else { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } + fclose(fp); if (err || bytes_read != data_size) { PyErr_SetString(PyExc_IOError, "zipimport: can't read data"); @@ -1477,12 +1329,12 @@ /* Return the code object for the module named by 'fullname' from the Zip archive as a new reference. */ static PyObject * -get_code_from_data(ZipImporter *self, FILE *fp, int ispackage, int isbytecode, +get_code_from_data(ZipImporter *self, int ispackage, int isbytecode, time_t mtime, PyObject *toc_entry) { PyObject *data, *modpath, *code; - data = get_data(fp, self->archive, toc_entry); + data = get_data(self->archive, toc_entry); if (data == NULL) return NULL; @@ -1504,7 +1356,6 @@ PyObject *code = NULL, *toc_entry, *subname; PyObject *path, *fullpath = NULL; struct st_zip_searchorder *zso; - FILE *fp; subname = get_subname(fullname); if (subname == NULL) @@ -1515,12 +1366,6 @@ if (path == NULL) return NULL; - fp = safely_reopen_archive(self); - if (fp == NULL) { - Py_DECREF(path); - return NULL; - } - for (zso = zip_searchorder; *zso->suffix; zso++) { code = NULL; @@ -1531,7 +1376,6 @@ if (Py_VerboseFlag > 1) PySys_FormatStderr("# trying %U%c%U\n", self->archive, (int)SEP, fullpath); - toc_entry = PyDict_GetItem(self->files, fullpath); if (toc_entry != NULL) { time_t mtime = 0; @@ -1547,7 +1391,7 @@ Py_CLEAR(fullpath); if (p_ispackage != NULL) *p_ispackage = ispackage; - code = get_code_from_data(self, fp, ispackage, + code = get_code_from_data(self, ispackage, isbytecode, mtime, toc_entry); if (code == Py_None) { @@ -1567,7 +1411,6 @@ } PyErr_Format(ZipImportError, "can't find module %R", fullname); exit: - fclose(fp); Py_DECREF(path); Py_XDECREF(fullpath); return code; @@ -1585,8 +1428,6 @@ subclass of ImportError, so it can be caught as ImportError, too.\n\ - _zip_directory_cache: a dict, mapping archive paths to zip directory\n\ info dicts, as used in zipimporter._files.\n\ -- _zip_stat_cache: a dict, mapping archive paths to stat_result\n\ - info for the .zip the last time anything was imported from it.\n\ \n\ It is usually not needed to use the zipimport module explicitly; it is\n\ used by the builtin import mechanism for sys.path items that are paths\n\ @@ -1646,7 +1487,6 @@ (PyObject *)&ZipImporter_Type) < 0) return NULL; - Py_XDECREF(zip_directory_cache); /* Avoid embedded interpreter leaks. */ zip_directory_cache = PyDict_New(); if (zip_directory_cache == NULL) return NULL; @@ -1654,36 +1494,5 @@ if (PyModule_AddObject(mod, "_zip_directory_cache", zip_directory_cache) < 0) return NULL; - - Py_XDECREF(zip_stat_cache); /* Avoid embedded interpreter leaks. */ - zip_stat_cache = PyDict_New(); - if (zip_stat_cache == NULL) - return NULL; - Py_INCREF(zip_stat_cache); - if (PyModule_AddObject(mod, "_zip_stat_cache", zip_stat_cache) < 0) - return NULL; - - { - /* We cannot import "os" here as that is a .py/.pyc file that could - * live within a zipped up standard library. Import the posix or nt - * builtin that provides the fstat() function we want instead. */ - PyObject *os_like_module; - Py_CLEAR(fstat_function); /* Avoid embedded interpreter leaks. */ - os_like_module = PyImport_ImportModule("posix"); - if (os_like_module == NULL) { - PyErr_Clear(); - os_like_module = PyImport_ImportModule("nt"); - } - if (os_like_module != NULL) { - fstat_function = PyObject_GetAttrString(os_like_module, "fstat"); - Py_DECREF(os_like_module); - } - if (fstat_function == NULL) { - PyErr_Clear(); /* non-fatal, we'll go on without it. */ - if (Py_VerboseFlag) - PySys_WriteStderr("# zipimport unable to use os.fstat().\n"); - } - } - return mod; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 20:21:48 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 20:21:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge_backout_for_=2320621?= Message-ID: <3fRyqw56CFz7Ljq@mail.python.org> http://hg.python.org/cpython/rev/52ab9e1ff46a changeset: 89222:52ab9e1ff46a parent: 89219:b328f8ccbccf parent: 89221:5330de5c9d2d user: Benjamin Peterson date: Sun Feb 16 14:17:28 2014 -0500 summary: merge backout for #20621 files: Lib/test/test_zipimport.py | 104 +------- Modules/zipimport.c | 286 ++++-------------------- 2 files changed, 68 insertions(+), 322 deletions(-) diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -71,27 +71,6 @@ support.modules_cleanup(*self.modules_before) -def _write_zip_package(zipname, files, - data_to_prepend=b"", compression=ZIP_STORED): - z = ZipFile(zipname, "w") - try: - for name, (mtime, data) in files.items(): - zinfo = ZipInfo(name, time.localtime(mtime)) - zinfo.compress_type = compression - z.writestr(zinfo, data) - finally: - z.close() - - if data_to_prepend: - # Prepend data to the start of the zipfile - with open(zipname, "rb") as f: - zip_data = f.read() - - with open(zipname, "wb") as f: - f.write(data_to_prepend) - f.write(zip_data) - - class UncompressedZipImportTestCase(ImportHooksBaseTestCase): compression = ZIP_STORED @@ -104,9 +83,23 @@ ImportHooksBaseTestCase.setUp(self) def doTest(self, expected_ext, files, *modules, **kw): - _write_zip_package(TEMP_ZIP, files, data_to_prepend=kw.get("stuff"), - compression=self.compression) + z = ZipFile(TEMP_ZIP, "w") try: + for name, (mtime, data) in files.items(): + zinfo = ZipInfo(name, time.localtime(mtime)) + zinfo.compress_type = self.compression + z.writestr(zinfo, data) + z.close() + + stuff = kw.get("stuff", None) + if stuff is not None: + # Prepend 'stuff' to the start of the zipfile + with open(TEMP_ZIP, "rb") as f: + data = f.read() + with open(TEMP_ZIP, "wb") as f: + f.write(stuff) + f.write(data) + sys.path.insert(0, TEMP_ZIP) mod = __import__(".".join(modules), globals(), locals(), @@ -121,8 +114,7 @@ self.assertEqual(file, os.path.join(TEMP_ZIP, *modules) + expected_ext) finally: - while TEMP_ZIP in sys.path: - sys.path.remove(TEMP_ZIP) + z.close() os.remove(TEMP_ZIP) def testAFakeZlib(self): @@ -430,67 +422,10 @@ compression = ZIP_DEFLATED -class ZipFileModifiedAfterImportTestCase(ImportHooksBaseTestCase): - def setUp(self): - zipimport._zip_directory_cache.clear() - zipimport._zip_stat_cache.clear() - ImportHooksBaseTestCase.setUp(self) - - def tearDown(self): - ImportHooksBaseTestCase.tearDown(self) - if os.path.exists(TEMP_ZIP): - os.remove(TEMP_ZIP) - - def testZipFileChangesAfterFirstImport(self): - """Alter the zip file after caching its index and try an import.""" - packdir = TESTPACK + os.sep - files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc), - packdir + TESTMOD + ".py": (NOW, "test_value = 38\n"), - "ziptest_a.py": (NOW, "test_value = 23\n"), - "ziptest_b.py": (NOW, "test_value = 42\n"), - "ziptest_c.py": (NOW, "test_value = 1337\n")} - zipfile_path = TEMP_ZIP - _write_zip_package(zipfile_path, files) - self.assertTrue(os.path.exists(zipfile_path)) - sys.path.insert(0, zipfile_path) - - # Import something out of the zipfile and confirm it is correct. - testmod = __import__(TESTPACK + "." + TESTMOD, - globals(), locals(), ["__dummy__"]) - self.assertEqual(testmod.test_value, 38) - # Import something else out of the zipfile and confirm it is correct. - ziptest_b = __import__("ziptest_b", globals(), locals(), ["test_value"]) - self.assertEqual(ziptest_b.test_value, 42) - - # Truncate and fill the zip file with non-zip garbage. - with open(zipfile_path, "rb") as orig_zip_file: - orig_zip_file_contents = orig_zip_file.read() - with open(zipfile_path, "wb") as byebye_valid_zip_file: - byebye_valid_zip_file.write(b"Tear down this wall!\n"*1987) - # Now that the zipfile has been replaced, import something else from it - # which should fail as the file contents are now garbage. - with self.assertRaises(ImportError): - ziptest_a = __import__("ziptest_a", globals(), locals(), - ["test_value"]) - self.assertEqual(ziptest_a.test_value, 23) - - # Now lets make it a valid zipfile that has some garbage at the start. - # This alters all of the offsets within the file - with open(zipfile_path, "wb") as new_zip_file: - new_zip_file.write(b"X"*1991) # The year Python was created. - new_zip_file.write(orig_zip_file_contents) - - # Now that the zip file has been "restored" to a valid but different - # zipfile the zipimporter should *successfully* re-read the new zip - # file's end of file central index and be able to import from it again. - ziptest_c = __import__("ziptest_c", globals(), locals(), ["test_value"]) - self.assertEqual(ziptest_c.test_value, 1337) - - class BadFileZipImportTestCase(unittest.TestCase): def assertZipFailure(self, filename): - with self.assertRaises(zipimport.ZipImportError): - zipimport.zipimporter(filename) + self.assertRaises(zipimport.ZipImportError, + zipimport.zipimporter, filename) def testNoFile(self): self.assertZipFailure('AdfjdkFJKDFJjdklfjs') @@ -564,7 +499,6 @@ UncompressedZipImportTestCase, CompressedZipImportTestCase, BadFileZipImportTestCase, - ZipFileModifiedAfterImportTestCase, ) finally: support.unlink(TESTMOD) diff --git a/Modules/zipimport.c b/Modules/zipimport.c --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -49,16 +49,10 @@ static PyObject *ZipImportError; /* read_directory() cache */ static PyObject *zip_directory_cache = NULL; -static PyObject *zip_stat_cache = NULL; -/* posix.fstat or nt.fstat function. Used due to posixmodule.c's - * superior fstat implementation over libc's on Windows. */ -static PyObject *fstat_function = NULL; /* posix.fstat() or nt.fstat() */ /* forward decls */ -static FILE *fopen_rb_and_stat(PyObject *path, PyObject **py_stat_p); -static FILE *safely_reopen_archive(ZipImporter *self); -static PyObject *read_directory(FILE *fp, PyObject *archive); -static PyObject *get_data(FILE *fp, PyObject *archive, PyObject *toc_entry); +static PyObject *read_directory(PyObject *archive); +static PyObject *get_data(PyObject *archive, PyObject *toc_entry); static PyObject *get_module_code(ZipImporter *self, PyObject *fullname, int *p_ispackage, PyObject **p_modpath); @@ -137,39 +131,11 @@ files = PyDict_GetItem(zip_directory_cache, filename); if (files == NULL) { - PyObject *zip_stat = NULL; - FILE *fp = fopen_rb_and_stat(filename, &zip_stat); - if (fp == NULL) { - if (!PyErr_Occurred()) - PyErr_Format(ZipImportError, "can't open Zip file: %R", - filename); - - Py_XDECREF(zip_stat); + files = read_directory(filename); + if (files == NULL) goto error; - } - - if (Py_VerboseFlag) - PySys_FormatStderr("# zipimport: %U not cached, " - "reading TOC.\n", filename); - - files = read_directory(fp, filename); - fclose(fp); - if (files == NULL) { - Py_XDECREF(zip_stat); + if (PyDict_SetItem(zip_directory_cache, filename, files) != 0) goto error; - } - if (PyDict_SetItem(zip_directory_cache, filename, files) != 0) { - Py_DECREF(files); - Py_XDECREF(zip_stat); - goto error; - } - if (zip_stat && PyDict_SetItem(zip_stat_cache, filename, - zip_stat) != 0) { - Py_DECREF(files); - Py_DECREF(zip_stat); - goto error; - } - Py_XDECREF(zip_stat); } else Py_INCREF(files); @@ -594,8 +560,7 @@ { ZipImporter *self = (ZipImporter *)obj; PyObject *path, *key; - FILE *fp; - PyObject *toc_entry, *data; + PyObject *toc_entry; Py_ssize_t path_start, path_len, len; if (!PyArg_ParseTuple(args, "U:zipimporter.get_data", &path)) @@ -623,23 +588,15 @@ key = PyUnicode_Substring(path, path_start, path_len); if (key == NULL) goto error; - - fp = safely_reopen_archive(self); - if (fp == NULL) - goto error; - toc_entry = PyDict_GetItem(self->files, key); if (toc_entry == NULL) { PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, key); Py_DECREF(key); - fclose(fp); goto error; } Py_DECREF(key); Py_DECREF(path); - data = get_data(fp, self->archive, toc_entry); - fclose(fp); - return data; + return get_data(self->archive, toc_entry); error: Py_DECREF(path); return NULL; @@ -664,7 +621,6 @@ PyObject *toc_entry; PyObject *fullname, *subname, *path, *fullpath; enum zi_module_info mi; - FILE *fp; if (!PyArg_ParseTuple(args, "U:zipimporter.get_source", &fullname)) return NULL; @@ -694,18 +650,11 @@ if (fullpath == NULL) return NULL; - fp = safely_reopen_archive(self); - if (fp == NULL) { - Py_DECREF(fullpath); - return NULL; - } - toc_entry = PyDict_GetItem(self->files, fullpath); Py_DECREF(fullpath); if (toc_entry != NULL) { PyObject *res, *bytes; - bytes = get_data(fp, self->archive, toc_entry); - fclose(fp); + bytes = get_data(self->archive, toc_entry); if (bytes == NULL) return NULL; res = PyUnicode_FromStringAndSize(PyBytes_AS_STRING(bytes), @@ -713,10 +662,10 @@ Py_DECREF(bytes); return res; } - fclose(fp); /* we have the module, but no source */ - Py_RETURN_NONE; + Py_INCREF(Py_None); + return Py_None; } PyDoc_STRVAR(doc_find_module, @@ -882,133 +831,10 @@ return x; } -/* Return 1 if objects a and b fail a Py_EQ test for an attr. */ -static int -compare_obj_attr_strings(PyObject *obj_a, PyObject *obj_b, char *attr_name) -{ - int problem = 0; - PyObject *attr_a = PyObject_GetAttrString(obj_a, attr_name); - PyObject *attr_b = PyObject_GetAttrString(obj_b, attr_name); - if (attr_a == NULL || attr_b == NULL) - problem = 1; - else - problem = (PyObject_RichCompareBool(attr_a, attr_b, Py_EQ) != 1); - Py_XDECREF(attr_a); - Py_XDECREF(attr_b); - return problem; -} +/* + read_directory(archive) -> files dict (new reference) -/* - * Returns an open FILE * on success. - * Returns NULL on error with the Python error context set. - */ -static FILE * -safely_reopen_archive(ZipImporter *self) -{ - FILE *fp; - PyObject *stat_now = NULL; - - fp = fopen_rb_and_stat(self->archive, &stat_now); - if (!fp) { - PyErr_Format(ZipImportError, - "zipimport: can not open file %U", self->archive); - Py_XDECREF(stat_now); - return NULL; - } - - if (stat_now != NULL) { - int problem = 0; - PyObject *files; - PyObject *prev_stat = PyDict_GetItem(zip_stat_cache, self->archive); - /* Test stat_now vs the old cached stat on some key attributes. */ - if (prev_stat != NULL) { - problem = compare_obj_attr_strings(prev_stat, stat_now, - "st_ino"); - problem |= compare_obj_attr_strings(prev_stat, stat_now, - "st_size"); - problem |= compare_obj_attr_strings(prev_stat, stat_now, - "st_mtime"); - } else { - if (Py_VerboseFlag) - PySys_FormatStderr("# zipimport: no stat data for %U!\n", - self->archive); - problem = 1; - } - - if (problem) { - if (Py_VerboseFlag) - PySys_FormatStderr("# zipimport: %U modified since last" - " import, rereading TOC.\n", self->archive); - files = read_directory(fp, self->archive); - if (files == NULL) { - Py_DECREF(stat_now); - fclose(fp); - return NULL; - } - if (PyDict_SetItem(zip_directory_cache, self->archive, - files) != 0) { - Py_DECREF(files); - Py_DECREF(stat_now); - fclose(fp); - return NULL; - } - if (stat_now && PyDict_SetItem(zip_stat_cache, self->archive, - stat_now) != 0) { - Py_DECREF(files); - Py_DECREF(stat_now); - fclose(fp); - return NULL; - } - Py_XDECREF(self->files); /* free the old value. */ - self->files = files; - } - Py_DECREF(stat_now); - } /* stat succeeded */ - - return fp; -} - -/* - fopen_rb_and_stat(path, &py_stat) -> FILE * - - Opens path in "rb" mode and populates the Python py_stat stat_result - with information about the opened file. *py_stat may not be changed - if there is no fstat_function or if fstat_function fails. - - Returns NULL and does nothing to *py_stat if the open failed. -*/ -static FILE * -fopen_rb_and_stat(PyObject *path, PyObject **py_stat_p) -{ - FILE *fp; - assert(py_stat_p != NULL); - assert(*py_stat_p == NULL); - - fp = _Py_fopen_obj(path, "rb"); - if (fp == NULL) { - if (!PyErr_Occurred()) - PyErr_Format(ZipImportError, - "zipimport: can not open file %U", path); - return NULL; - } - - if (fstat_function) { - PyObject *stat_result = PyObject_CallFunction(fstat_function, - "i", fileno(fp)); - if (stat_result == NULL) { - PyErr_Clear(); /* We can function without it. */ - } else { - *py_stat_p = stat_result; - } - } - - return fp; -} - -/* - read_directory(fp, archive) -> files dict (new reference) - - Given an open Zip archive, build a dict, mapping file names + Given a path to a Zip archive, build a dict, mapping file names (local to the archive, using SEP as a separator) to toc entries. A toc_entry is a tuple: @@ -1028,9 +854,10 @@ data_size and file_offset are 0. */ static PyObject * -read_directory(FILE *fp, PyObject *archive) +read_directory(PyObject *archive) { PyObject *files = NULL; + FILE *fp; unsigned short flags; short compress, time, date, name_size; long crc, data_size, file_size, header_size; @@ -1046,18 +873,27 @@ const char *charset; int bootstrap; - assert(fp != NULL); + fp = _Py_fopen_obj(archive, "rb"); + if (fp == NULL) { + if (!PyErr_Occurred()) + PyErr_Format(ZipImportError, "can't open Zip file: %R", archive); + return NULL; + } + if (fseek(fp, -22, SEEK_END) == -1) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } header_position = ftell(fp); if (fread(endof_central_dir, 1, 22, fp) != 22) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) { /* Bad: End of Central Dir signature */ + fclose(fp); PyErr_Format(ZipImportError, "not a Zip file: %R", archive); return NULL; } @@ -1164,16 +1000,19 @@ goto error; count++; } + fclose(fp); if (Py_VerboseFlag) PySys_FormatStderr("# zipimport: found %ld names in %R\n", count, archive); return files; file_error: + fclose(fp); Py_XDECREF(files); Py_XDECREF(nameobj); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; error: + fclose(fp); Py_XDECREF(files); Py_XDECREF(nameobj); return NULL; @@ -1212,13 +1051,14 @@ return decompress; } -/* Given a FILE* to a Zip file and a toc_entry, return the (uncompressed) +/* Given a path to a Zip file and a toc_entry, return the (uncompressed) data as a new reference. */ static PyObject * -get_data(FILE *fp, PyObject *archive, PyObject *toc_entry) +get_data(PyObject *archive, PyObject *toc_entry) { PyObject *raw_data, *data = NULL, *decompress; char *buf; + FILE *fp; int err; Py_ssize_t bytes_read = 0; long l; @@ -1232,8 +1072,17 @@ return NULL; } + fp = _Py_fopen_obj(archive, "rb"); + if (!fp) { + if (!PyErr_Occurred()) + PyErr_Format(PyExc_IOError, + "zipimport: can not open file %U", archive); + return NULL; + } + /* Check to make sure the local file header is correct */ if (fseek(fp, file_offset, 0) == -1) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } @@ -1245,9 +1094,11 @@ PyErr_Format(ZipImportError, "bad local file header in %U", archive); + fclose(fp); return NULL; } if (fseek(fp, file_offset + 26, 0) == -1) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } @@ -1255,6 +1106,7 @@ l = 30 + PyMarshal_ReadShortFromFile(fp) + PyMarshal_ReadShortFromFile(fp); /* local header size */ if (PyErr_Occurred()) { + fclose(fp); return NULL; } file_offset += l; /* Start of file data */ @@ -1265,6 +1117,7 @@ raw_data = PyBytes_FromStringAndSize((char *)NULL, bytes_size); if (raw_data == NULL) { + fclose(fp); return NULL; } buf = PyBytes_AsString(raw_data); @@ -1273,9 +1126,11 @@ if (err == 0) { bytes_read = fread(buf, 1, data_size, fp); } else { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); return NULL; } + fclose(fp); if (err || bytes_read != data_size) { PyErr_SetString(PyExc_IOError, "zipimport: can't read data"); @@ -1496,12 +1351,12 @@ /* Return the code object for the module named by 'fullname' from the Zip archive as a new reference. */ static PyObject * -get_code_from_data(ZipImporter *self, FILE *fp, int ispackage, int isbytecode, +get_code_from_data(ZipImporter *self, int ispackage, int isbytecode, time_t mtime, PyObject *toc_entry) { PyObject *data, *modpath, *code; - data = get_data(fp, self->archive, toc_entry); + data = get_data(self->archive, toc_entry); if (data == NULL) return NULL; @@ -1523,7 +1378,6 @@ PyObject *code = NULL, *toc_entry, *subname; PyObject *path, *fullpath = NULL; struct st_zip_searchorder *zso; - FILE *fp; subname = get_subname(fullname); if (subname == NULL) @@ -1534,12 +1388,6 @@ if (path == NULL) return NULL; - fp = safely_reopen_archive(self); - if (fp == NULL) { - Py_DECREF(path); - return NULL; - } - for (zso = zip_searchorder; *zso->suffix; zso++) { code = NULL; @@ -1550,7 +1398,6 @@ if (Py_VerboseFlag > 1) PySys_FormatStderr("# trying %U%c%U\n", self->archive, (int)SEP, fullpath); - toc_entry = PyDict_GetItem(self->files, fullpath); if (toc_entry != NULL) { time_t mtime = 0; @@ -1566,7 +1413,7 @@ Py_CLEAR(fullpath); if (p_ispackage != NULL) *p_ispackage = ispackage; - code = get_code_from_data(self, fp, ispackage, + code = get_code_from_data(self, ispackage, isbytecode, mtime, toc_entry); if (code == Py_None) { @@ -1586,7 +1433,6 @@ } PyErr_Format(ZipImportError, "can't find module %R", fullname); exit: - fclose(fp); Py_DECREF(path); Py_XDECREF(fullpath); return code; @@ -1604,8 +1450,6 @@ subclass of ImportError, so it can be caught as ImportError, too.\n\ - _zip_directory_cache: a dict, mapping archive paths to zip directory\n\ info dicts, as used in zipimporter._files.\n\ -- _zip_stat_cache: a dict, mapping archive paths to stat_result\n\ - info for the .zip the last time anything was imported from it.\n\ \n\ It is usually not needed to use the zipimport module explicitly; it is\n\ used by the builtin import mechanism for sys.path items that are paths\n\ @@ -1665,7 +1509,6 @@ (PyObject *)&ZipImporter_Type) < 0) return NULL; - Py_XDECREF(zip_directory_cache); /* Avoid embedded interpreter leaks. */ zip_directory_cache = PyDict_New(); if (zip_directory_cache == NULL) return NULL; @@ -1673,36 +1516,5 @@ if (PyModule_AddObject(mod, "_zip_directory_cache", zip_directory_cache) < 0) return NULL; - - Py_XDECREF(zip_stat_cache); /* Avoid embedded interpreter leaks. */ - zip_stat_cache = PyDict_New(); - if (zip_stat_cache == NULL) - return NULL; - Py_INCREF(zip_stat_cache); - if (PyModule_AddObject(mod, "_zip_stat_cache", zip_stat_cache) < 0) - return NULL; - - { - /* We cannot import "os" here as that is a .py/.pyc file that could - * live within a zipped up standard library. Import the posix or nt - * builtin that provides the fstat() function we want instead. */ - PyObject *os_like_module; - Py_CLEAR(fstat_function); /* Avoid embedded interpreter leaks. */ - os_like_module = PyImport_ImportModule("posix"); - if (os_like_module == NULL) { - PyErr_Clear(); - os_like_module = PyImport_ImportModule("nt"); - } - if (os_like_module != NULL) { - fstat_function = PyObject_GetAttrString(os_like_module, "fstat"); - Py_DECREF(os_like_module); - } - if (fstat_function == NULL) { - PyErr_Clear(); /* non-fatal, we'll go on without it. */ - if (Py_VerboseFlag) - PySys_WriteStderr("# zipimport unable to use os.fstat().\n"); - } - } - return mod; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 20:21:50 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 20:21:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogYmFja291dCAjMTkw?= =?utf-8?q?81_to_fix_=2320621?= Message-ID: <3fRyqy2G5rz7LkG@mail.python.org> http://hg.python.org/cpython/rev/3dd8b0d31543 changeset: 89223:3dd8b0d31543 branch: 2.7 parent: 89202:a87f284e14ea user: Benjamin Peterson date: Sun Feb 16 14:20:14 2014 -0500 summary: backout #19081 to fix #20621 files: Lib/test/test_zipimport.py | 132 +++---------------- Misc/NEWS | 5 - Modules/zipimport.c | 168 +++++++++--------------- 3 files changed, 88 insertions(+), 217 deletions(-) diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -395,145 +395,57 @@ def setUp(self): zipimport._zip_directory_cache.clear() zipimport._zip_stat_cache.clear() - # save sys.modules so we can unimport everything done by our tests. - self._sys_modules_orig = dict(sys.modules) ImportHooksBaseTestCase.setUp(self) def tearDown(self): ImportHooksBaseTestCase.tearDown(self) - # The closest we can come to un-importing our zipped up test modules. - sys.modules.clear() - sys.modules.update(self._sys_modules_orig) if os.path.exists(TEMP_ZIP): os.remove(TEMP_ZIP) - def setUpZipFileModuleAndTestImports(self): - # Create a .zip file to test with - self.zipfile_path = TEMP_ZIP + def testZipFileChangesAfterFirstImport(self): + """Alter the zip file after caching its index and try an import.""" packdir = TESTPACK + os.sep files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc), packdir + TESTMOD + ".py": (NOW, "test_value = 38\n"), "ziptest_a.py": (NOW, "test_value = 23\n"), "ziptest_b.py": (NOW, "test_value = 42\n"), "ziptest_c.py": (NOW, "test_value = 1337\n")} - _write_zip_package(self.zipfile_path, files) - self.assertTrue(os.path.exists(self.zipfile_path)) - sys.path.insert(0, self.zipfile_path) - - self.testpack_testmod = TESTPACK + "." + TESTMOD - - with io.open(self.zipfile_path, "rb") as orig_zip_file: - self.orig_zip_file_contents = orig_zip_file.read() + zipfile_path = TEMP_ZIP + _write_zip_package(zipfile_path, files) + self.assertTrue(os.path.exists(zipfile_path)) + sys.path.insert(0, zipfile_path) # Import something out of the zipfile and confirm it is correct. - testmod = __import__(self.testpack_testmod, + testmod = __import__(TESTPACK + "." + TESTMOD, globals(), locals(), ["__dummy__"]) self.assertEqual(testmod.test_value, 38) - del sys.modules[TESTPACK] - del sys.modules[self.testpack_testmod] - # Import something else out of the zipfile and confirm it is correct. ziptest_b = __import__("ziptest_b", globals(), locals(), ["test_value"]) self.assertEqual(ziptest_b.test_value, 42) - del sys.modules["ziptest_b"] - def truncateAndFillZipWithNonZipGarbage(self): - with io.open(self.zipfile_path, "wb") as byebye_valid_zip_file: + # Truncate and fill the zip file with non-zip garbage. + with io.open(zipfile_path, "rb") as orig_zip_file: + orig_zip_file_contents = orig_zip_file.read() + with io.open(zipfile_path, "wb") as byebye_valid_zip_file: byebye_valid_zip_file.write(b"Tear down this wall!\n"*1987) - - def restoreZipFileWithDifferentHeaderOffsets(self): - """Make it a valid zipfile with some garbage at the start.""" - # This alters all of the caches offsets within the file. - with io.open(self.zipfile_path, "wb") as new_zip_file: - new_zip_file.write(b"X"*1991) # The year Python was created. - new_zip_file.write(self.orig_zip_file_contents) - - def testZipFileChangesAfterFirstImport(self): - """Alter the zip file after caching its index and try an import.""" - self.setUpZipFileModuleAndTestImports() - # The above call cached the .zip table of contents during its tests. - self.truncateAndFillZipWithNonZipGarbage() # Now that the zipfile has been replaced, import something else from it # which should fail as the file contents are now garbage. with self.assertRaises(ImportError): - ziptest_a = __import__("ziptest_a", {}, {}, ["test_value"]) - # The code path used by the __import__ call is different than - # that used by import statements. Try these as well. Some of - # these may create new zipimporter instances. We need to - # function properly using the global zipimport caches - # regardless of how many zipimporter instances for the same - # .zip file exist. - with self.assertRaises(ImportError): - import ziptest_a - with self.assertRaises(ImportError): - from ziptest_a import test_value - with self.assertRaises(ImportError): - exec("from {} import {}".format(TESTPACK, TESTMOD), {}) + ziptest_a = __import__("ziptest_a", globals(), locals(), + ["test_value"]) - # Alters all of the offsets within the file - self.restoreZipFileWithDifferentHeaderOffsets() + # Now lets make it a valid zipfile that has some garbage at the start. + # This alters all of the offsets within the file + with io.open(zipfile_path, "wb") as new_zip_file: + new_zip_file.write(b"X"*1991) # The year Python was created. + new_zip_file.write(orig_zip_file_contents) # Now that the zip file has been "restored" to a valid but different - # zipfile all zipimporter instances should *successfully* re-read the - # new file's end of file central index and be able to import again. - - # Importing a submodule triggers a different import code path. - test_ns = {} - exec("import " + self.testpack_testmod, test_ns) - self.assertEqual(getattr(test_ns[TESTPACK], TESTMOD).test_value, 38) - test_ns = {} - exec("from {} import {}".format(TESTPACK, TESTMOD), test_ns) - self.assertEqual(test_ns[TESTMOD].test_value, 38) - - ziptest_a = __import__("ziptest_a", {}, {}, ["test_value"]) + # zipfile the zipimporter should *successfully* re-read the new zip + # file's end of file central index and be able to import from it again. + ziptest_a = __import__("ziptest_a", globals(), locals(), ["test_value"]) self.assertEqual(ziptest_a.test_value, 23) - ziptest_c = __import__("ziptest_c", {}, {}, ["test_value"]) - self.assertEqual(ziptest_c.test_value, 1337) - - def testZipFileSubpackageImport(self): - """Import via multiple sys.path entries into parts of the zip.""" - self.setUpZipFileModuleAndTestImports() - # Put a subdirectory within the zip file into the import path. - sys.path.insert(0, self.zipfile_path + os.sep + TESTPACK) - - testmod = __import__(TESTMOD, {}, {}, ["test_value"]) - self.assertEqual(testmod.test_value, 38) - del sys.modules[TESTMOD] - test_ns = {} - exec("from {} import test_value".format(TESTMOD), test_ns) - self.assertEqual(test_ns["test_value"], 38) - del sys.modules[TESTMOD] - - # Confirm that imports from the top level of the zip file - # (already in sys.path from the setup call above) still work. - ziptest_a = __import__("ziptest_a", {}, {}, ["test_value"]) - self.assertEqual(ziptest_a.test_value, 23) - del sys.modules["ziptest_a"] - import ziptest_c - self.assertEqual(ziptest_c.test_value, 1337) - del sys.modules["ziptest_c"] - - self.truncateAndFillZipWithNonZipGarbage() - # Imports should now fail. - with self.assertRaises(ImportError): - testmod = __import__(TESTMOD, {}, {}, ["test_value"]) - with self.assertRaises(ImportError): - exec("from {} import test_value".format(TESTMOD), {}) - with self.assertRaises(ImportError): - import ziptest_a - - self.restoreZipFileWithDifferentHeaderOffsets() - # Imports should work again, the central directory TOC will be re-read. - testmod = __import__(TESTMOD, {}, {}, ["test_value"]) - self.assertEqual(testmod.test_value, 38) - del sys.modules[TESTMOD] - test_ns = {} - exec("from {} import test_value".format(TESTMOD), test_ns) - self.assertEqual(test_ns['test_value'], 38) - - ziptest_a = __import__("ziptest_a", {}, {}, ["test_value"]) - self.assertEqual(ziptest_a.test_value, 23) - import ziptest_c + ziptest_c = __import__("ziptest_c", globals(), locals(), ["test_value"]) self.assertEqual(ziptest_c.test_value, 1337) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -18,11 +18,6 @@ - Issue #17825: Cursor "^" is correctly positioned for SyntaxError and IndentationError. -- Issue #19081: When a zipimport .zip file in sys.path being imported from - is modified during the lifetime of the Python process after zipimport has - already cached the zip's table of contents we detect this and recover - rather than read bad data from the .zip (causing odd import errors). - - Raise a better error when non-unicode codecs are used for a file's coding cookie. diff --git a/Modules/zipimport.c b/Modules/zipimport.c --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -66,34 +66,30 @@ static int zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds) { - char *path_arg, *path, *p, *prefix, *path_buf; + char *path, *p, *prefix, buf[MAXPATHLEN+2]; size_t len; if (!_PyArg_NoKeywords("zipimporter()", kwds)) return -1; - if (!PyArg_ParseTuple(args, "s:zipimporter", &path_arg)) + if (!PyArg_ParseTuple(args, "s:zipimporter", + &path)) return -1; - len = strlen(path_arg); + len = strlen(path); if (len == 0) { PyErr_SetString(ZipImportError, "archive path is empty"); return -1; } if (len >= MAXPATHLEN) { - PyErr_SetString(ZipImportError, "archive path too long"); + PyErr_SetString(ZipImportError, + "archive path too long"); return -1; } - /* Room for the trailing \0 and room for an extra SEP if needed. */ - path_buf = (char *)PyMem_Malloc(len + 2); - if (path_buf == NULL) { - PyErr_SetString(PyExc_MemoryError, "unable to malloc path buffer"); - return -1; - } - strcpy(path_buf, path_arg); + strcpy(buf, path); #ifdef ALTSEP - for (p = path_buf; *p; p++) { + for (p = buf; *p; p++) { if (*p == ALTSEP) *p = SEP; } @@ -106,25 +102,25 @@ struct stat statbuf; int rv; - rv = stat(path_buf, &statbuf); + rv = stat(buf, &statbuf); if (rv == 0) { /* it exists */ if (S_ISREG(statbuf.st_mode)) /* it's a file */ - path = path_buf; + path = buf; break; } #else - if (object_exists(path_buf)) { + if (object_exists(buf)) { /* it exists */ - if (isfile(path_buf)) + if (isfile(buf)) /* it's a file */ - path = path_buf; + path = buf; break; } #endif /* back up one path element */ - p = strrchr(path_buf, SEP); + p = strrchr(buf, SEP); if (prefix != NULL) *prefix = SEP; if (p == NULL) @@ -137,42 +133,45 @@ files = PyDict_GetItemString(zip_directory_cache, path); if (files == NULL) { PyObject *zip_stat = NULL; - FILE *fp = fopen_rb_and_stat(path, &zip_stat); + FILE *fp = fopen_rb_and_stat(buf, &zip_stat); if (fp == NULL) { PyErr_Format(ZipImportError, "can't open Zip file: " - "'%.200s'", path); + "'%.200s'", buf); Py_XDECREF(zip_stat); - goto error; + return -1; } if (Py_VerboseFlag) PySys_WriteStderr("# zipimport: %s not cached, " "reading TOC.\n", path); - files = read_directory(fp, path); + files = read_directory(fp, buf); fclose(fp); if (files == NULL) { Py_XDECREF(zip_stat); - goto error; + return -1; } if (PyDict_SetItemString(zip_directory_cache, path, files) != 0) { Py_DECREF(files); Py_XDECREF(zip_stat); - goto error; + return -1; } if (zip_stat && PyDict_SetItemString(zip_stat_cache, path, zip_stat) != 0) { Py_DECREF(files); Py_DECREF(zip_stat); - goto error; + return -1; } Py_XDECREF(zip_stat); } + else + Py_INCREF(files); + self->files = files; } else { PyErr_SetString(ZipImportError, "not a Zip file"); - goto error; + return -1; } if (prefix == NULL) @@ -187,26 +186,33 @@ } } - self->archive = PyString_FromString(path); + self->archive = PyString_FromString(buf); if (self->archive == NULL) - goto error; + return -1; self->prefix = PyString_FromString(prefix); if (self->prefix == NULL) - goto error; + return -1; - PyMem_Free(path_buf); return 0; -error: - PyMem_Free(path_buf); - return -1; +} + +/* GC support. */ +static int +zipimporter_traverse(PyObject *obj, visitproc visit, void *arg) +{ + ZipImporter *self = (ZipImporter *)obj; + Py_VISIT(self->files); + return 0; } static void zipimporter_dealloc(ZipImporter *self) { + PyObject_GC_UnTrack(self); Py_XDECREF(self->archive); Py_XDECREF(self->prefix); + Py_XDECREF(self->files); Py_TYPE(self)->tp_free((PyObject *)self); } @@ -286,7 +292,6 @@ char *subname, path[MAXPATHLEN + 1]; int len; struct st_zip_searchorder *zso; - PyObject *files; subname = get_subname(fullname); @@ -294,23 +299,9 @@ if (len < 0) return MI_ERROR; - files = PyDict_GetItem(zip_directory_cache, self->archive); - if (files == NULL) { - /* Some scoundrel has cleared zip_directory_cache out from - * beneath us. Try repopulating it once before giving up. */ - char *unused_archive_name; - FILE *fp = safely_reopen_archive(self, &unused_archive_name); - if (fp == NULL) - return MI_ERROR; - fclose(fp); - files = PyDict_GetItem(zip_directory_cache, self->archive); - if (files == NULL) - return MI_ERROR; - } - for (zso = zip_searchorder; *zso->suffix; zso++) { strcpy(path + len, zso->suffix); - if (PyDict_GetItemString(files, path) != NULL) { + if (PyDict_GetItemString(self->files, path) != NULL) { if (zso->type & IS_PACKAGE) return MI_PACKAGE; else @@ -465,7 +456,7 @@ #ifdef ALTSEP char *p, buf[MAXPATHLEN + 1]; #endif - PyObject *toc_entry, *data, *files; + PyObject *toc_entry, *data; Py_ssize_t len; if (!PyArg_ParseTuple(args, "s:zipimporter.get_data", &path)) @@ -494,13 +485,7 @@ if (fp == NULL) return NULL; - files = PyDict_GetItem(zip_directory_cache, self->archive); - if (files == NULL) { - /* This should never happen as safely_reopen_archive() should - * have repopulated zip_directory_cache if needed. */ - return NULL; - } - toc_entry = PyDict_GetItemString(files, path); + toc_entry = PyDict_GetItemString(self->files, path); if (toc_entry == NULL) { PyErr_SetFromErrnoWithFilename(PyExc_IOError, path); fclose(fp); @@ -527,7 +512,7 @@ zipimporter_get_source(PyObject *obj, PyObject *args) { ZipImporter *self = (ZipImporter *)obj; - PyObject *toc_entry, *files; + PyObject *toc_entry; FILE *fp; char *fullname, *subname, path[MAXPATHLEN+1], *archive; int len; @@ -561,13 +546,7 @@ if (fp == NULL) return NULL; - files = PyDict_GetItem(zip_directory_cache, self->archive); - if (files == NULL) { - /* This should never happen as safely_reopen_archive() should - * have repopulated zip_directory_cache if needed. */ - return NULL; - } - toc_entry = PyDict_GetItemString(files, path); + toc_entry = PyDict_GetItemString(self->files, path); if (toc_entry != NULL) { PyObject *data = get_data(fp, archive, toc_entry); fclose(fp); @@ -687,9 +666,10 @@ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, /* tp_flags */ zipimporter_doc, /* tp_doc */ - 0, /* tp_traverse */ + zipimporter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -706,7 +686,7 @@ (initproc)zipimporter_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ + PyObject_GC_Del, /* tp_free */ }; @@ -850,13 +830,13 @@ fclose(fp); return NULL; } + Py_XDECREF(self->files); /* free the old value. */ + self->files = files; + } else { + /* No problem, discard the new stat data. */ + Py_DECREF(stat_now); } - Py_DECREF(stat_now); - } else { - if (Py_VerboseFlag) - PySys_WriteStderr("# zipimport: os.fstat failed on the " - "open %s file.\n", archive); - } + } /* stat succeeded */ return fp; } @@ -1258,18 +1238,12 @@ static time_t get_mtime_of_source(ZipImporter *self, char *path) { - PyObject *toc_entry, *files; + PyObject *toc_entry; time_t mtime = 0; Py_ssize_t lastchar = strlen(path) - 1; char savechar = path[lastchar]; path[lastchar] = '\0'; /* strip 'c' or 'o' from *.py[co] */ - files = PyDict_GetItem(zip_directory_cache, self->archive); - if (files == NULL) { - /* This should never happen as safely_reopen_archive() from - * our only caller repopulated zip_directory_cache if needed. */ - return 0; - } - toc_entry = PyDict_GetItemString(files, path); + toc_entry = PyDict_GetItemString(self->files, path); if (toc_entry != NULL && PyTuple_Check(toc_entry) && PyTuple_Size(toc_entry) == 8) { /* fetch the time stamp of the .py file for comparison @@ -1318,8 +1292,6 @@ char *subname, path[MAXPATHLEN + 1]; int len; struct st_zip_searchorder *zso; - FILE *fp; - char *archive; subname = get_subname(fullname); @@ -1327,12 +1299,10 @@ if (len < 0) return NULL; - fp = safely_reopen_archive(self, &archive); - if (fp == NULL) - return NULL; - for (zso = zip_searchorder; *zso->suffix; zso++) { - PyObject *code = NULL, *files; + PyObject *code = NULL; + FILE *fp; + char *archive; strcpy(path + len, zso->suffix); if (Py_VerboseFlag > 1) @@ -1340,14 +1310,11 @@ PyString_AsString(self->archive), SEP, path); - files = PyDict_GetItem(zip_directory_cache, self->archive); - if (files == NULL) { - /* This should never happen as safely_reopen_archive() should - * have repopulated zip_directory_cache if needed; and the GIL - * is being held. */ + fp = safely_reopen_archive(self, &archive); + if (fp == NULL) return NULL; - } - toc_entry = PyDict_GetItemString(files, path); + + toc_entry = PyDict_GetItemString(self->files, path); if (toc_entry != NULL) { time_t mtime = 0; int ispackage = zso->type & IS_PACKAGE; @@ -1360,6 +1327,7 @@ code = get_code_from_data(archive, fp, ispackage, isbytecode, mtime, toc_entry); + fclose(fp); if (code == Py_None) { /* bad magic number or non-matching mtime in byte code, try next */ @@ -1369,12 +1337,11 @@ if (code != NULL && p_modpath != NULL) *p_modpath = PyString_AsString( PyTuple_GetItem(toc_entry, 0)); - fclose(fp); return code; } + fclose(fp); } PyErr_Format(ZipImportError, "can't find module '%.200s'", fullname); - fclose(fp); return NULL; } @@ -1462,10 +1429,9 @@ * live within a zipped up standard library. Import the posix or nt * builtin that provides the fstat() function we want instead. */ PyObject *os_like_module; - Py_CLEAR(fstat_function); /* Avoid embedded interpreter leaks. */ + Py_XDECREF(fstat_function); /* Avoid embedded interpreter leaks. */ os_like_module = PyImport_ImportModule("posix"); if (os_like_module == NULL) { - PyErr_Clear(); os_like_module = PyImport_ImportModule("nt"); } if (os_like_module != NULL) { @@ -1474,8 +1440,6 @@ } if (fstat_function == NULL) { PyErr_Clear(); /* non-fatal, we'll go on without it. */ - if (Py_VerboseFlag) - PySys_WriteStderr("# zipimport unable to use os.fstat().\n"); } } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 20:47:16 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 20:47:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_finish_backing?= =?utf-8?q?_out_=2319081?= Message-ID: <3fRzPJ43Q0z7LjY@mail.python.org> http://hg.python.org/cpython/rev/10f09881320d changeset: 89224:10f09881320d branch: 2.7 user: Benjamin Peterson date: Sun Feb 16 14:46:57 2014 -0500 summary: finish backing out #19081 files: Modules/zipimport.c | 296 +++++-------------------------- 1 files changed, 54 insertions(+), 242 deletions(-) diff --git a/Modules/zipimport.c b/Modules/zipimport.c --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -42,16 +42,10 @@ static PyObject *ZipImportError; static PyObject *zip_directory_cache = NULL; -static PyObject *zip_stat_cache = NULL; -/* posix.fstat or nt.fstat function. Used due to posixmodule.c's - * superior fstat implementation over libc's on Windows. */ -static PyObject *fstat_function = NULL; /* posix.fstat() or nt.fstat() */ /* forward decls */ -static FILE *fopen_rb_and_stat(char *path, PyObject **py_stat_p); -static FILE *safely_reopen_archive(ZipImporter *self, char **archive_p); -static PyObject *read_directory(FILE *fp, char *archive); -static PyObject *get_data(FILE *fp, char *archive, PyObject *toc_entry); +static PyObject *read_directory(char *archive); +static PyObject *get_data(char *archive, PyObject *toc_entry); static PyObject *get_module_code(ZipImporter *self, char *fullname, int *p_ispackage, char **p_modpath); @@ -132,38 +126,12 @@ PyObject *files; files = PyDict_GetItemString(zip_directory_cache, path); if (files == NULL) { - PyObject *zip_stat = NULL; - FILE *fp = fopen_rb_and_stat(buf, &zip_stat); - if (fp == NULL) { - PyErr_Format(ZipImportError, "can't open Zip file: " - "'%.200s'", buf); - Py_XDECREF(zip_stat); + files = read_directory(buf); + if (files == NULL) return -1; - } - - if (Py_VerboseFlag) - PySys_WriteStderr("# zipimport: %s not cached, " - "reading TOC.\n", path); - - files = read_directory(fp, buf); - fclose(fp); - if (files == NULL) { - Py_XDECREF(zip_stat); + if (PyDict_SetItemString(zip_directory_cache, path, + files) != 0) return -1; - } - if (PyDict_SetItemString(zip_directory_cache, path, - files) != 0) { - Py_DECREF(files); - Py_XDECREF(zip_stat); - return -1; - } - if (zip_stat && PyDict_SetItemString(zip_stat_cache, path, - zip_stat) != 0) { - Py_DECREF(files); - Py_DECREF(zip_stat); - return -1; - } - Py_XDECREF(zip_stat); } else Py_INCREF(files); @@ -451,12 +419,11 @@ zipimporter_get_data(PyObject *obj, PyObject *args) { ZipImporter *self = (ZipImporter *)obj; - char *path, *archive; - FILE *fp; + char *path; #ifdef ALTSEP char *p, buf[MAXPATHLEN + 1]; #endif - PyObject *toc_entry, *data; + PyObject *toc_entry; Py_ssize_t len; if (!PyArg_ParseTuple(args, "s:zipimporter.get_data", &path)) @@ -481,19 +448,12 @@ path = path + len + 1; } - fp = safely_reopen_archive(self, &archive); - if (fp == NULL) - return NULL; - toc_entry = PyDict_GetItemString(self->files, path); if (toc_entry == NULL) { PyErr_SetFromErrnoWithFilename(PyExc_IOError, path); - fclose(fp); return NULL; } - data = get_data(fp, archive, toc_entry); - fclose(fp); - return data; + return get_data(PyString_AsString(self->archive), toc_entry); } static PyObject * @@ -513,8 +473,7 @@ { ZipImporter *self = (ZipImporter *)obj; PyObject *toc_entry; - FILE *fp; - char *fullname, *subname, path[MAXPATHLEN+1], *archive; + char *fullname, *subname, path[MAXPATHLEN+1]; int len; enum zi_module_info mi; @@ -542,20 +501,13 @@ else strcpy(path + len, ".py"); - fp = safely_reopen_archive(self, &archive); - if (fp == NULL) - return NULL; - toc_entry = PyDict_GetItemString(self->files, path); - if (toc_entry != NULL) { - PyObject *data = get_data(fp, archive, toc_entry); - fclose(fp); - return data; - } - fclose(fp); + if (toc_entry != NULL) + return get_data(PyString_AsString(self->archive), toc_entry); /* we have the module, but no source */ - Py_RETURN_NONE; + Py_INCREF(Py_None); + return Py_None; } PyDoc_STRVAR(doc_find_module, @@ -710,139 +662,7 @@ } /* - fopen_rb_and_stat(path, &py_stat) -> FILE * - - Opens path in "rb" mode and populates the Python py_stat stat_result - with information about the opened file. *py_stat may not be changed - if there is no fstat_function or if fstat_function fails. - - Returns NULL and does nothing to *py_stat if the open failed. -*/ -static FILE * -fopen_rb_and_stat(char *path, PyObject **py_stat_p) -{ - FILE *fp; - assert(py_stat_p != NULL); - assert(*py_stat_p == NULL); - - fp = fopen(path, "rb"); - if (fp == NULL) { - return NULL; - } - - if (fstat_function) { - PyObject *stat_result = PyObject_CallFunction(fstat_function, - "i", fileno(fp)); - if (stat_result == NULL) { - PyErr_Clear(); /* We can function without it. */ - } else { - *py_stat_p = stat_result; - } - } - - return fp; -} - -/* Return 1 if objects a and b fail a Py_EQ test for an attr. */ -static int -compare_obj_attr_strings(PyObject *obj_a, PyObject *obj_b, char *attr_name) -{ - int problem = 0; - PyObject *attr_a = PyObject_GetAttrString(obj_a, attr_name); - PyObject *attr_b = PyObject_GetAttrString(obj_b, attr_name); - if (attr_a == NULL || attr_b == NULL) - problem = 1; - else - problem = (PyObject_RichCompareBool(attr_a, attr_b, Py_EQ) != 1); - Py_XDECREF(attr_a); - Py_XDECREF(attr_b); - return problem; -} - -/* - * Returns an open FILE * on success and sets *archive_p to point to - * a read only C string representation of the archive name (as a - * convenience for use in error messages). - * - * Returns NULL on error with the Python error context set. - */ -static FILE * -safely_reopen_archive(ZipImporter *self, char **archive_p) -{ - FILE *fp; - PyObject *stat_now = NULL; - char *archive; - - assert(archive_p != NULL); - *archive_p = PyString_AsString(self->archive); - if (*archive_p == NULL) - return NULL; - archive = *archive_p; - - fp = fopen_rb_and_stat(archive, &stat_now); - if (!fp) { - PyErr_Format(PyExc_IOError, - "zipimport: can not open file %s", archive); - Py_XDECREF(stat_now); - return NULL; - } - - if (stat_now != NULL) { - int problem = 0; - PyObject *files; - PyObject *prev_stat = PyDict_GetItemString(zip_stat_cache, archive); - /* Test stat_now vs the old cached stat on some key attributes. */ - if (prev_stat != NULL) { - problem = compare_obj_attr_strings(prev_stat, stat_now, - "st_ino"); - problem |= compare_obj_attr_strings(prev_stat, stat_now, - "st_size"); - problem |= compare_obj_attr_strings(prev_stat, stat_now, - "st_mtime"); - } else { - if (Py_VerboseFlag) - PySys_WriteStderr("# zipimport: no stat data for %s!\n", - archive); - problem = 1; - } - - if (problem) { - if (Py_VerboseFlag) - PySys_WriteStderr("# zipimport: %s modified since last" - " import, rereading TOC.\n", archive); - files = read_directory(fp, archive); - if (files == NULL) { - Py_DECREF(stat_now); - fclose(fp); - return NULL; - } - if (PyDict_SetItem(zip_directory_cache, self->archive, - files) != 0) { - Py_DECREF(files); - Py_DECREF(stat_now); - fclose(fp); - return NULL; - } - if (stat_now && PyDict_SetItem(zip_stat_cache, self->archive, - stat_now) != 0) { - Py_DECREF(files); - Py_DECREF(stat_now); - fclose(fp); - return NULL; - } - Py_XDECREF(self->files); /* free the old value. */ - self->files = files; - } else { - /* No problem, discard the new stat data. */ - Py_DECREF(stat_now); - } - } /* stat succeeded */ - - return fp; -} - -/* - read_directory(fp, archive) -> files dict (new reference) + read_directory(archive) -> files dict (new reference) Given a path to a Zip archive, build a dict, mapping file names (local to the archive, using SEP as a separator) to toc entries. @@ -863,9 +683,10 @@ data_size and file_offset are 0. */ static PyObject * -read_directory(FILE *fp, char *archive) +read_directory(char *archive) { PyObject *files = NULL; + FILE *fp; long compress, crc, data_size, file_size, file_offset, date, time; long header_offset, name_size, header_size, header_position; long i, l, count; @@ -875,7 +696,6 @@ char *p, endof_central_dir[22]; long arc_offset; /* offset from beginning of file to start of zip-archive */ - assert(fp != NULL); if (strlen(archive) > MAXPATHLEN) { PyErr_SetString(PyExc_OverflowError, "Zip path name is too long"); @@ -883,18 +703,28 @@ } strcpy(path, archive); + fp = fopen(archive, "rb"); + if (fp == NULL) { + PyErr_Format(ZipImportError, "can't open Zip file: " + "'%.200s'", archive); + return NULL; + } + if (fseek(fp, -22, SEEK_END) == -1) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %s", archive); return NULL; } header_position = ftell(fp); if (fread(endof_central_dir, 1, 22, fp) != 22) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: " "'%.200s'", archive); return NULL; } if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) { /* Bad: End of Central Dir signature */ + fclose(fp); PyErr_Format(ZipImportError, "not a Zip file: " "'%.200s'", archive); return NULL; @@ -963,15 +793,18 @@ goto error; count++; } + fclose(fp); if (Py_VerboseFlag) PySys_WriteStderr("# zipimport: found %ld names in %s\n", count, archive); return files; fseek_error: + fclose(fp); Py_XDECREF(files); PyErr_Format(ZipImportError, "can't read Zip file: %s", archive); return NULL; error: + fclose(fp); Py_XDECREF(files); return NULL; } @@ -1008,13 +841,14 @@ return decompress; } -/* Given a FILE* to a Zip file and a toc_entry, return the (uncompressed) +/* Given a path to a Zip file and a toc_entry, return the (uncompressed) data as a new reference. */ static PyObject * -get_data(FILE *fp, char *archive, PyObject *toc_entry) +get_data(char *archive, PyObject *toc_entry) { PyObject *raw_data, *data = NULL, *decompress; char *buf; + FILE *fp; int err; Py_ssize_t bytes_read = 0; long l; @@ -1028,8 +862,16 @@ return NULL; } + fp = fopen(archive, "rb"); + if (!fp) { + PyErr_Format(PyExc_IOError, + "zipimport: can not open file %s", archive); + return NULL; + } + /* Check to make sure the local file header is correct */ if (fseek(fp, file_offset, 0) == -1) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %s", archive); return NULL; } @@ -1040,9 +882,11 @@ PyErr_Format(ZipImportError, "bad local file header in %s", archive); + fclose(fp); return NULL; } if (fseek(fp, file_offset + 26, 0) == -1) { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %s", archive); return NULL; } @@ -1054,6 +898,7 @@ raw_data = PyString_FromStringAndSize((char *)NULL, compress == 0 ? data_size : data_size + 1); if (raw_data == NULL) { + fclose(fp); return NULL; } buf = PyString_AsString(raw_data); @@ -1062,9 +907,11 @@ if (err == 0) { bytes_read = fread(buf, 1, data_size, fp); } else { + fclose(fp); PyErr_Format(ZipImportError, "can't read Zip file: %s", archive); return NULL; } + fclose(fp); if (err || bytes_read != data_size) { PyErr_SetString(PyExc_IOError, "zipimport: can't read data"); @@ -1260,13 +1107,17 @@ /* Return the code object for the module named by 'fullname' from the Zip archive as a new reference. */ static PyObject * -get_code_from_data(char *archive, FILE *fp, int ispackage, - int isbytecode, time_t mtime, PyObject *toc_entry) +get_code_from_data(ZipImporter *self, int ispackage, int isbytecode, + time_t mtime, PyObject *toc_entry) { PyObject *data, *code; char *modpath; + char *archive = PyString_AsString(self->archive); - data = get_data(fp, archive, toc_entry); + if (archive == NULL) + return NULL; + + data = get_data(archive, toc_entry); if (data == NULL) return NULL; @@ -1301,19 +1152,12 @@ for (zso = zip_searchorder; *zso->suffix; zso++) { PyObject *code = NULL; - FILE *fp; - char *archive; strcpy(path + len, zso->suffix); if (Py_VerboseFlag > 1) PySys_WriteStderr("# trying %s%c%s\n", PyString_AsString(self->archive), SEP, path); - - fp = safely_reopen_archive(self, &archive); - if (fp == NULL) - return NULL; - toc_entry = PyDict_GetItemString(self->files, path); if (toc_entry != NULL) { time_t mtime = 0; @@ -1324,10 +1168,9 @@ mtime = get_mtime_of_source(self, path); if (p_ispackage != NULL) *p_ispackage = ispackage; - code = get_code_from_data(archive, fp, ispackage, + code = get_code_from_data(self, ispackage, isbytecode, mtime, toc_entry); - fclose(fp); if (code == Py_None) { /* bad magic number or non-matching mtime in byte code, try next */ @@ -1339,7 +1182,6 @@ PyTuple_GetItem(toc_entry, 0)); return code; } - fclose(fp); } PyErr_Format(ZipImportError, "can't find module '%.200s'", fullname); return NULL; @@ -1357,8 +1199,6 @@ subclass of ImportError, so it can be caught as ImportError, too.\n\ - _zip_directory_cache: a dict, mapping archive paths to zip directory\n\ info dicts, as used in zipimporter._files.\n\ -- _zip_stat_cache: a dict, mapping archive paths to stat_result\n\ - info for the .zip the last time anything was imported from it.\n\ \n\ It is usually not needed to use the zipimport module explicitly; it is\n\ used by the builtin import mechanism for sys.path items that are paths\n\ @@ -1407,7 +1247,6 @@ (PyObject *)&ZipImporter_Type) < 0) return; - Py_XDECREF(zip_directory_cache); /* Avoid embedded interpreter leaks. */ zip_directory_cache = PyDict_New(); if (zip_directory_cache == NULL) return; @@ -1415,31 +1254,4 @@ if (PyModule_AddObject(mod, "_zip_directory_cache", zip_directory_cache) < 0) return; - - Py_XDECREF(zip_stat_cache); /* Avoid embedded interpreter leaks. */ - zip_stat_cache = PyDict_New(); - if (zip_stat_cache == NULL) - return; - Py_INCREF(zip_stat_cache); - if (PyModule_AddObject(mod, "_zip_stat_cache", zip_stat_cache) < 0) - return; - - { - /* We cannot import "os" here as that is a .py/.pyc file that could - * live within a zipped up standard library. Import the posix or nt - * builtin that provides the fstat() function we want instead. */ - PyObject *os_like_module; - Py_XDECREF(fstat_function); /* Avoid embedded interpreter leaks. */ - os_like_module = PyImport_ImportModule("posix"); - if (os_like_module == NULL) { - os_like_module = PyImport_ImportModule("nt"); - } - if (os_like_module != NULL) { - fstat_function = PyObject_GetAttrString(os_like_module, "fstat"); - Py_DECREF(os_like_module); - } - if (fstat_function == NULL) { - PyErr_Clear(); /* non-fatal, we'll go on without it. */ - } - } } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 20:54:04 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 20:54:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_remove_tests_f?= =?utf-8?q?or_=2319081?= Message-ID: <3fRzY874PrzRSm@mail.python.org> http://hg.python.org/cpython/rev/3350c6b7aa28 changeset: 89225:3350c6b7aa28 branch: 2.7 user: Benjamin Peterson date: Sun Feb 16 14:48:26 2014 -0500 summary: remove tests for #19081 files: Lib/test/test_zipimport.py | 105 +++++-------------------- 1 files changed, 21 insertions(+), 84 deletions(-) diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -1,4 +1,3 @@ -import io import sys import os import marshal @@ -56,27 +55,6 @@ TEMP_ZIP = os.path.abspath("junk95142" + os.extsep + "zip") -def _write_zip_package(zipname, files, - data_to_prepend=b"", compression=ZIP_STORED): - z = ZipFile(zipname, "w") - try: - for name, (mtime, data) in files.items(): - zinfo = ZipInfo(name, time.localtime(mtime)) - zinfo.compress_type = compression - z.writestr(zinfo, data) - finally: - z.close() - - if data_to_prepend: - # Prepend data to the start of the zipfile - with open(zipname, "rb") as f: - zip_data = f.read() - - with open(zipname, "wb") as f: - f.write(data_to_prepend) - f.write(zip_data) - - class UncompressedZipImportTestCase(ImportHooksBaseTestCase): compression = ZIP_STORED @@ -89,9 +67,26 @@ ImportHooksBaseTestCase.setUp(self) def doTest(self, expected_ext, files, *modules, **kw): - _write_zip_package(TEMP_ZIP, files, data_to_prepend=kw.get("stuff"), - compression=self.compression) + z = ZipFile(TEMP_ZIP, "w") try: + for name, (mtime, data) in files.items(): + zinfo = ZipInfo(name, time.localtime(mtime)) + zinfo.compress_type = self.compression + z.writestr(zinfo, data) + z.close() + + stuff = kw.get("stuff", None) + if stuff is not None: + # Prepend 'stuff' to the start of the zipfile + f = open(TEMP_ZIP, "rb") + data = f.read() + f.close() + + f = open(TEMP_ZIP, "wb") + f.write(stuff) + f.write(data) + f.close() + sys.path.insert(0, TEMP_ZIP) mod = __import__(".".join(modules), globals(), locals(), @@ -106,6 +101,7 @@ self.assertEqual(file, os.path.join(TEMP_ZIP, *modules) + expected_ext) finally: + z.close() os.remove(TEMP_ZIP) def testAFakeZlib(self): @@ -127,7 +123,7 @@ # so we'll simply skip it then. Bug #765456. # if "zlib" in sys.builtin_module_names: - self.skipTest('zlib is a builtin module') + return if "zlib" in sys.modules: del sys.modules["zlib"] files = {"zlib.py": (NOW, test_src)} @@ -391,64 +387,6 @@ compression = ZIP_DEFLATED -class ZipFileModifiedAfterImportTestCase(ImportHooksBaseTestCase): - def setUp(self): - zipimport._zip_directory_cache.clear() - zipimport._zip_stat_cache.clear() - ImportHooksBaseTestCase.setUp(self) - - def tearDown(self): - ImportHooksBaseTestCase.tearDown(self) - if os.path.exists(TEMP_ZIP): - os.remove(TEMP_ZIP) - - def testZipFileChangesAfterFirstImport(self): - """Alter the zip file after caching its index and try an import.""" - packdir = TESTPACK + os.sep - files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc), - packdir + TESTMOD + ".py": (NOW, "test_value = 38\n"), - "ziptest_a.py": (NOW, "test_value = 23\n"), - "ziptest_b.py": (NOW, "test_value = 42\n"), - "ziptest_c.py": (NOW, "test_value = 1337\n")} - zipfile_path = TEMP_ZIP - _write_zip_package(zipfile_path, files) - self.assertTrue(os.path.exists(zipfile_path)) - sys.path.insert(0, zipfile_path) - - # Import something out of the zipfile and confirm it is correct. - testmod = __import__(TESTPACK + "." + TESTMOD, - globals(), locals(), ["__dummy__"]) - self.assertEqual(testmod.test_value, 38) - # Import something else out of the zipfile and confirm it is correct. - ziptest_b = __import__("ziptest_b", globals(), locals(), ["test_value"]) - self.assertEqual(ziptest_b.test_value, 42) - - # Truncate and fill the zip file with non-zip garbage. - with io.open(zipfile_path, "rb") as orig_zip_file: - orig_zip_file_contents = orig_zip_file.read() - with io.open(zipfile_path, "wb") as byebye_valid_zip_file: - byebye_valid_zip_file.write(b"Tear down this wall!\n"*1987) - # Now that the zipfile has been replaced, import something else from it - # which should fail as the file contents are now garbage. - with self.assertRaises(ImportError): - ziptest_a = __import__("ziptest_a", globals(), locals(), - ["test_value"]) - - # Now lets make it a valid zipfile that has some garbage at the start. - # This alters all of the offsets within the file - with io.open(zipfile_path, "wb") as new_zip_file: - new_zip_file.write(b"X"*1991) # The year Python was created. - new_zip_file.write(orig_zip_file_contents) - - # Now that the zip file has been "restored" to a valid but different - # zipfile the zipimporter should *successfully* re-read the new zip - # file's end of file central index and be able to import from it again. - ziptest_a = __import__("ziptest_a", globals(), locals(), ["test_value"]) - self.assertEqual(ziptest_a.test_value, 23) - ziptest_c = __import__("ziptest_c", globals(), locals(), ["test_value"]) - self.assertEqual(ziptest_c.test_value, 1337) - - class BadFileZipImportTestCase(unittest.TestCase): def assertZipFailure(self, filename): self.assertRaises(zipimport.ZipImportError, @@ -526,7 +464,6 @@ UncompressedZipImportTestCase, CompressedZipImportTestCase, BadFileZipImportTestCase, - ZipFileModifiedAfterImportTestCase, ) finally: test_support.unlink(TESTMOD) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 20:54:06 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 20:54:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_backout_369bf9?= =?utf-8?q?fbaeff?= Message-ID: <3fRzYB1k8Rz7Ljs@mail.python.org> http://hg.python.org/cpython/rev/47394ceeaba1 changeset: 89226:47394ceeaba1 branch: 2.7 user: Benjamin Peterson date: Sun Feb 16 14:51:17 2014 -0500 summary: backout 369bf9fbaeff files: Lib/test/regrtest.py | 11 ++++------- Lib/test/test_pkgutil.py | 4 +++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -1002,10 +1002,9 @@ try: import zipimport except ImportError: - zsc = zdc = None # Run unmodified on platforms without zipimport support + zdc = None # Run unmodified on platforms without zipimport support else: zdc = zipimport._zip_directory_cache.copy() - zsc = zipimport._zip_stat_cache.copy() abcs = {} modules = _abcoll, _pyio for abc in [getattr(mod, a) for mod in modules for a in mod.__all__]: @@ -1028,12 +1027,12 @@ repcount = nwarmup + ntracked print >> sys.stderr, "beginning", repcount, "repetitions" print >> sys.stderr, ("1234567890"*(repcount//10 + 1))[:repcount] - dash_R_cleanup(fs, ps, pic, zdc, zsc, abcs) + dash_R_cleanup(fs, ps, pic, zdc, abcs) for i in range(repcount): rc_before = sys.gettotalrefcount() run_the_test() sys.stderr.write('.') - dash_R_cleanup(fs, ps, pic, zdc, zsc, abcs) + dash_R_cleanup(fs, ps, pic, zdc, abcs) rc_after = sys.gettotalrefcount() if i >= nwarmup: deltas.append(rc_after - rc_before) @@ -1047,7 +1046,7 @@ return True return False -def dash_R_cleanup(fs, ps, pic, zdc, zsc, abcs): +def dash_R_cleanup(fs, ps, pic, zdc, abcs): import gc, copy_reg import _strptime, linecache dircache = test_support.import_module('dircache', deprecated=True) @@ -1073,8 +1072,6 @@ else: zipimport._zip_directory_cache.clear() zipimport._zip_directory_cache.update(zdc) - zipimport._zip_stat_cache.clear() - zipimport._zip_stat_cache.update(zsc) # clear type cache sys._clear_type_cache() diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -133,7 +133,9 @@ def test_main(): run_unittest(PkgutilTests, PkgutilPEP302Tests) - + # this is necessary if test is run repeated (like when finding leaks) + import zipimport + zipimport._zip_directory_cache.clear() if __name__ == '__main__': test_main() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 20:54:07 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 20:54:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_backout_fafac9?= =?utf-8?q?0b69c4?= Message-ID: <3fRzYC33qCz7Ljd@mail.python.org> http://hg.python.org/cpython/rev/478523c1aafc changeset: 89227:478523c1aafc branch: 3.3 parent: 89221:5330de5c9d2d user: Benjamin Peterson date: Sun Feb 16 14:52:01 2014 -0500 summary: backout fafac90b69c4 files: Lib/test/regrtest.py | 11 ++++------- Lib/test/test_pkgutil.py | 5 +++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -1318,10 +1318,9 @@ try: import zipimport except ImportError: - zsc = zdc = None # Run unmodified on platforms without zipimport support + zdc = None # Run unmodified on platforms without zipimport support else: zdc = zipimport._zip_directory_cache.copy() - zsc = zipimport._zip_stat_cache.copy() abcs = {} for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]: if not isabstract(abc): @@ -1344,13 +1343,13 @@ print("beginning", repcount, "repetitions", file=sys.stderr) print(("1234567890"*(repcount//10 + 1))[:repcount], file=sys.stderr) sys.stderr.flush() - dash_R_cleanup(fs, ps, pic, zdc, zsc, abcs) + dash_R_cleanup(fs, ps, pic, zdc, abcs) for i in range(repcount): rc_before = sys.gettotalrefcount() run_the_test() sys.stderr.write('.') sys.stderr.flush() - dash_R_cleanup(fs, ps, pic, zdc, zsc, abcs) + dash_R_cleanup(fs, ps, pic, zdc, abcs) rc_after = sys.gettotalrefcount() if i >= nwarmup: deltas.append(rc_after - rc_before) @@ -1365,7 +1364,7 @@ return True return False -def dash_R_cleanup(fs, ps, pic, zdc, zsc, abcs): +def dash_R_cleanup(fs, ps, pic, zdc, abcs): import gc, copyreg import _strptime, linecache import urllib.parse, urllib.request, mimetypes, doctest @@ -1391,8 +1390,6 @@ else: zipimport._zip_directory_cache.clear() zipimport._zip_directory_cache.update(zdc) - zipimport._zip_stat_cache.clear() - zipimport._zip_stat_cache.update(zsc) # clear type cache sys._clear_type_cache() diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -338,6 +338,11 @@ def test_main(): run_unittest(PkgutilTests, PkgutilPEP302Tests, ExtendPathTests, NestedNamespacePackageTest, ImportlibMigrationTests) + # this is necessary if test is run repeated (like when finding leaks) + import zipimport + import importlib + zipimport._zip_directory_cache.clear() + importlib.invalidate_caches() if __name__ == '__main__': -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 20:54:08 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 16 Feb 2014 20:54:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4z?= Message-ID: <3fRzYD4j0Zz7LkC@mail.python.org> http://hg.python.org/cpython/rev/9487c290e088 changeset: 89228:9487c290e088 parent: 89222:52ab9e1ff46a parent: 89227:478523c1aafc user: Benjamin Peterson date: Sun Feb 16 14:53:55 2014 -0500 summary: merge 3.3 files: Lib/test/regrtest.py | 9 +++------ Lib/test/test_pkgutil.py | 5 +++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -1373,10 +1373,9 @@ try: import zipimport except ImportError: - zsc = zdc = None # Run unmodified on platforms without zipimport support + zdc = None # Run unmodified on platforms without zipimport support else: zdc = zipimport._zip_directory_cache.copy() - zsc = zipimport._zip_stat_cache.copy() abcs = {} for abc in [getattr(collections.abc, a) for a in collections.abc.__all__]: if not isabstract(abc): @@ -1395,7 +1394,7 @@ sys.stderr.flush() for i in range(repcount): indirect_test() - alloc_after, rc_after = dash_R_cleanup(fs, ps, pic, zdc, zsc, abcs) + alloc_after, rc_after = dash_R_cleanup(fs, ps, pic, zdc, abcs) sys.stderr.write('.') sys.stderr.flush() if i >= nwarmup: @@ -1429,7 +1428,7 @@ failed = True return failed -def dash_R_cleanup(fs, ps, pic, zdc, zsc, abcs): +def dash_R_cleanup(fs, ps, pic, zdc, abcs): import gc, copyreg import _strptime, linecache import urllib.parse, urllib.request, mimetypes, doctest @@ -1455,8 +1454,6 @@ else: zipimport._zip_directory_cache.clear() zipimport._zip_directory_cache.update(zdc) - zipimport._zip_stat_cache.clear() - zipimport._zip_stat_cache.update(zsc) # clear type cache sys._clear_type_cache() diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -349,6 +349,11 @@ def test_main(): run_unittest(PkgutilTests, PkgutilPEP302Tests, ExtendPathTests, NestedNamespacePackageTest, ImportlibMigrationTests) + # this is necessary if test is run repeated (like when finding leaks) + import zipimport + import importlib + zipimport._zip_directory_cache.clear() + importlib.invalidate_caches() if __name__ == '__main__': -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 16 23:03:37 2014 From: python-checkins at python.org (georg.brandl) Date: Sun, 16 Feb 2014 23:03:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_3=2E3_release_schedule?= =?utf-8?b?IGZvciAzLjMuNS4=?= Message-ID: <3fS2Qd0Pkdz7Ljr@mail.python.org> http://hg.python.org/peps/rev/723dfdc8912e changeset: 5374:723dfdc8912e user: Georg Brandl date: Sun Feb 16 23:04:27 2014 +0100 summary: Update 3.3 release schedule for 3.3.5. files: pep-0398.txt | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pep-0398.txt b/pep-0398.txt --- a/pep-0398.txt +++ b/pep-0398.txt @@ -94,12 +94,18 @@ 3.3.5 schedule -------------- -Python 3.3.5 will be the last regular maintenance release, released at some +- 3.3.5 candidate 1: February 22, 2014 +- 3.3.5 final: March 1, 2014 + +3.3.6 schedule +-------------- + +Python 3.3.6 will be the last regular maintenance release, released at some point after 3.4.0 final (see :pep:`429`), before 3.3 goes into security-fix only mode. -- 3.3.5 candidate 1: around May 2014 -- 3.3.5 final: two weeks later +- 3.3.6 candidate 1: around May 2014 +- 3.3.6 final: two weeks later Features for 3.3 ================ -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Feb 16 23:54:39 2014 From: python-checkins at python.org (victor.stinner) Date: Sun, 16 Feb 2014 23:54:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320616=3A_Add_a_fo?= =?utf-8?q?rmat=28=29_method_to_tracemalloc=2ETraceback=2E?= Message-ID: <3fS3YW2w8bz7LjY@mail.python.org> http://hg.python.org/cpython/rev/d50a95fab002 changeset: 89229:d50a95fab002 user: Victor Stinner date: Sun Feb 16 23:53:38 2014 +0100 summary: Issue #20616: Add a format() method to tracemalloc.Traceback. files: Doc/library/tracemalloc.rst | 31 ++++++++++++++++++----- Lib/test/test_tracemalloc.py | 20 +++++++++++++++ Lib/tracemalloc.py | 13 ++++++++++ Misc/NEWS | 2 + 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/Doc/library/tracemalloc.rst b/Doc/library/tracemalloc.rst --- a/Doc/library/tracemalloc.rst +++ b/Doc/library/tracemalloc.rst @@ -118,7 +118,6 @@ Code to display the traceback of the biggest memory block:: - import linecache import tracemalloc # Store 25 frames @@ -132,12 +131,8 @@ # pick the biggest memory block stat = top_stats[0] print("%s memory blocks: %.1f KiB" % (stat.count, stat.size / 1024)) - for frame in stat.traceback: - print(' File "%s", line %s' % (frame.filename, frame.lineno)) - line = linecache.getline(frame.filename, frame.lineno) - line = line.strip() - if line: - print(' ' + line) + for line in stat.traceback.format(): + print(line) Example of output of the Python test suite (traceback limited to 25 frames):: @@ -602,4 +597,26 @@ The :attr:`Trace.traceback` attribute is an instance of :class:`Traceback` instance. + .. method:: format(limit=None) + Format the traceback as a list of lines with newlines. Use the + :mod:`linecache` module to retrieve lines from the source code. If + *limit* is set, only format the *limit* most recent frames. + + Similar to the :func:`traceback.format_tb` function, except that + :meth:`format` does not include newlines. + + Example:: + + print("Traceback (most recent call first):") + for line in traceback: + print(line) + + Output:: + + Traceback (most recent call first): + File "test.py", line 9 + obj = Object() + File "test.py", line 12 + tb = tracemalloc.get_object_traceback(f()) + diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py --- a/Lib/test/test_tracemalloc.py +++ b/Lib/test/test_tracemalloc.py @@ -510,6 +510,26 @@ self.assertEqual(traceback[:2], (traceback[0], traceback[1])) + def test_format_traceback(self): + snapshot, snapshot2 = create_snapshots() + def getline(filename, lineno): + return ' <%s, %s>' % (filename, lineno) + with unittest.mock.patch('tracemalloc.linecache.getline', + side_effect=getline): + tb = snapshot.traces[0].traceback + self.assertEqual(tb.format(), + [' File "a.py", line 2', + ' ', + ' File "b.py", line 4', + ' ']) + + self.assertEqual(tb.format(limit=1), + [' File "a.py", line 2', + ' ']) + + self.assertEqual(tb.format(limit=-1), + []) + class TestFilters(unittest.TestCase): maxDiff = 2048 diff --git a/Lib/tracemalloc.py b/Lib/tracemalloc.py --- a/Lib/tracemalloc.py +++ b/Lib/tracemalloc.py @@ -1,6 +1,7 @@ from collections import Sequence from functools import total_ordering import fnmatch +import linecache import os.path import pickle @@ -205,6 +206,18 @@ def __repr__(self): return "" % (tuple(self),) + def format(self, limit=None): + lines = [] + if limit is not None and limit < 0: + return lines + for frame in self[:limit]: + lines.append(' File "%s", line %s' + % (frame.filename, frame.lineno)) + line = linecache.getline(frame.filename, frame.lineno).strip() + if line: + lines.append(' %s' % line) + return lines + def get_object_traceback(obj): """ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,6 +25,8 @@ Library ------- +- Issue #20616: Add a format() method to tracemalloc.Traceback. + - Issue #19744: the ensurepip installation step now just prints a warning to stderr rather than failing outright if SSL/TLS is unavailable. This allows local installation of POSIX builds without SSL/TLS support. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 17 00:08:28 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 17 Feb 2014 00:08:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320320=3A_select?= =?utf-8?q?=2Eselect=28=29_and_select=2Ekqueue=2Econtrol=28=29_now_round_t?= =?utf-8?q?he_timeout?= Message-ID: <3fS3sS1MfSz7LjM@mail.python.org> http://hg.python.org/cpython/rev/180e4b678003 changeset: 89230:180e4b678003 user: Victor Stinner date: Mon Feb 17 00:02:43 2014 +0100 summary: Issue #20320: select.select() and select.kqueue.control() now round the timeout aways from zero, instead of rounding towards zero. It should make test_asyncio more reliable, especially test_timeout_rounding() test. files: Include/pytime.h | 17 ++- Lib/test/test_time.py | 130 +++++++++++++++++++------- Misc/NEWS | 3 + Modules/_datetimemodule.c | 4 +- Modules/_testcapimodule.c | 31 +++++- Modules/posixmodule.c | 4 +- Modules/selectmodule.c | 10 +- Modules/signalmodule.c | 3 +- Modules/timemodule.c | 4 +- Python/pytime.c | 35 +++++- 10 files changed, 179 insertions(+), 62 deletions(-) diff --git a/Include/pytime.h b/Include/pytime.h --- a/Include/pytime.h +++ b/Include/pytime.h @@ -53,10 +53,19 @@ (tv_end.tv_usec - tv_start.tv_usec) * 0.000001) #ifndef Py_LIMITED_API + +typedef enum { + /* Round towards zero. */ + _PyTime_ROUND_DOWN=0, + /* Round away from zero. */ + _PyTime_ROUND_UP +} _PyTime_round_t; + /* Convert a number of seconds, int or float, to time_t. */ PyAPI_FUNC(int) _PyTime_ObjectToTime_t( PyObject *obj, - time_t *sec); + time_t *sec, + _PyTime_round_t); /* Convert a time_t to a PyLong. */ PyAPI_FUNC(PyObject *) _PyLong_FromTime_t( @@ -72,7 +81,8 @@ PyAPI_FUNC(int) _PyTime_ObjectToTimeval( PyObject *obj, time_t *sec, - long *usec); + long *usec, + _PyTime_round_t); /* Convert a number of seconds, int or float, to a timespec structure. nsec is in the range [0; 999999999] and rounded towards zero. @@ -80,7 +90,8 @@ PyAPI_FUNC(int) _PyTime_ObjectToTimespec( PyObject *obj, time_t *sec, - long *nsec); + long *nsec, + _PyTime_round_t); #endif /* Dummy to force linking. */ diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -14,6 +14,8 @@ SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4 TIME_MAXYEAR = (1 << 8 * SIZEOF_INT - 1) - 1 TIME_MINYEAR = -TIME_MAXYEAR - 1 +_PyTime_ROUND_DOWN = 0 +_PyTime_ROUND_UP = 1 class TimeTestCase(unittest.TestCase): @@ -585,58 +587,116 @@ @support.cpython_only def test_time_t(self): from _testcapi import pytime_object_to_time_t - for obj, time_t in ( - (0, 0), - (-1, -1), - (-1.0, -1), - (-1.9, -1), - (1.0, 1), - (1.9, 1), + for obj, time_t, rnd in ( + # Round towards zero + (0, 0, _PyTime_ROUND_DOWN), + (-1, -1, _PyTime_ROUND_DOWN), + (-1.0, -1, _PyTime_ROUND_DOWN), + (-1.9, -1, _PyTime_ROUND_DOWN), + (1.0, 1, _PyTime_ROUND_DOWN), + (1.9, 1, _PyTime_ROUND_DOWN), + # Round away from zero + (0, 0, _PyTime_ROUND_UP), + (-1, -1, _PyTime_ROUND_UP), + (-1.0, -1, _PyTime_ROUND_UP), + (-1.9, -2, _PyTime_ROUND_UP), + (1.0, 1, _PyTime_ROUND_UP), + (1.9, 2, _PyTime_ROUND_UP), ): - self.assertEqual(pytime_object_to_time_t(obj), time_t) + self.assertEqual(pytime_object_to_time_t(obj, rnd), time_t) + rnd = _PyTime_ROUND_DOWN for invalid in self.invalid_values: - self.assertRaises(OverflowError, pytime_object_to_time_t, invalid) + self.assertRaises(OverflowError, + pytime_object_to_time_t, invalid, rnd) @support.cpython_only def test_timeval(self): from _testcapi import pytime_object_to_timeval - for obj, timeval in ( - (0, (0, 0)), - (-1, (-1, 0)), - (-1.0, (-1, 0)), - (1e-6, (0, 1)), - (-1e-6, (-1, 999999)), - (-1.2, (-2, 800000)), - (1.1234560, (1, 123456)), - (1.1234569, (1, 123456)), - (-1.1234560, (-2, 876544)), - (-1.1234561, (-2, 876543)), + for obj, timeval, rnd in ( + # Round towards zero + (0, (0, 0), _PyTime_ROUND_DOWN), + (-1, (-1, 0), _PyTime_ROUND_DOWN), + (-1.0, (-1, 0), _PyTime_ROUND_DOWN), + (1e-6, (0, 1), _PyTime_ROUND_DOWN), + (1e-7, (0, 0), _PyTime_ROUND_DOWN), + (-1e-6, (-1, 999999), _PyTime_ROUND_DOWN), + (-1e-7, (-1, 999999), _PyTime_ROUND_DOWN), + (-1.2, (-2, 800000), _PyTime_ROUND_DOWN), + (0.9999999, (0, 999999), _PyTime_ROUND_DOWN), + (0.0000041, (0, 4), _PyTime_ROUND_DOWN), + (1.1234560, (1, 123456), _PyTime_ROUND_DOWN), + (1.1234569, (1, 123456), _PyTime_ROUND_DOWN), + (-0.0000040, (-1, 999996), _PyTime_ROUND_DOWN), + (-0.0000041, (-1, 999995), _PyTime_ROUND_DOWN), + (-1.1234560, (-2, 876544), _PyTime_ROUND_DOWN), + (-1.1234561, (-2, 876543), _PyTime_ROUND_DOWN), + # Round away from zero + (0, (0, 0), _PyTime_ROUND_UP), + (-1, (-1, 0), _PyTime_ROUND_UP), + (-1.0, (-1, 0), _PyTime_ROUND_UP), + (1e-6, (0, 1), _PyTime_ROUND_UP), + (1e-7, (0, 1), _PyTime_ROUND_UP), + (-1e-6, (-1, 999999), _PyTime_ROUND_UP), + (-1e-7, (-1, 999999), _PyTime_ROUND_UP), + (-1.2, (-2, 800000), _PyTime_ROUND_UP), + (0.9999999, (1, 0), _PyTime_ROUND_UP), + (0.0000041, (0, 5), _PyTime_ROUND_UP), + (1.1234560, (1, 123457), _PyTime_ROUND_UP), + (1.1234569, (1, 123457), _PyTime_ROUND_UP), + (-0.0000040, (-1, 999996), _PyTime_ROUND_UP), + (-0.0000041, (-1, 999995), _PyTime_ROUND_UP), + (-1.1234560, (-2, 876544), _PyTime_ROUND_UP), + (-1.1234561, (-2, 876543), _PyTime_ROUND_UP), ): - self.assertEqual(pytime_object_to_timeval(obj), timeval) + with self.subTest(obj=obj, round=rnd, timeval=timeval): + self.assertEqual(pytime_object_to_timeval(obj, rnd), timeval) + rnd = _PyTime_ROUND_DOWN for invalid in self.invalid_values: - self.assertRaises(OverflowError, pytime_object_to_timeval, invalid) + self.assertRaises(OverflowError, + pytime_object_to_timeval, invalid, rnd) @support.cpython_only def test_timespec(self): from _testcapi import pytime_object_to_timespec - for obj, timespec in ( - (0, (0, 0)), - (-1, (-1, 0)), - (-1.0, (-1, 0)), - (1e-9, (0, 1)), - (-1e-9, (-1, 999999999)), - (-1.2, (-2, 800000000)), - (1.1234567890, (1, 123456789)), - (1.1234567899, (1, 123456789)), - (-1.1234567890, (-2, 876543211)), - (-1.1234567891, (-2, 876543210)), + for obj, timespec, rnd in ( + # Round towards zero + (0, (0, 0), _PyTime_ROUND_DOWN), + (-1, (-1, 0), _PyTime_ROUND_DOWN), + (-1.0, (-1, 0), _PyTime_ROUND_DOWN), + (1e-9, (0, 1), _PyTime_ROUND_DOWN), + (1e-10, (0, 0), _PyTime_ROUND_DOWN), + (-1e-9, (-1, 999999999), _PyTime_ROUND_DOWN), + (-1e-10, (-1, 999999999), _PyTime_ROUND_DOWN), + (-1.2, (-2, 800000000), _PyTime_ROUND_DOWN), + (0.9999999999, (0, 999999999), _PyTime_ROUND_DOWN), + (1.1234567890, (1, 123456789), _PyTime_ROUND_DOWN), + (1.1234567899, (1, 123456789), _PyTime_ROUND_DOWN), + (-1.1234567890, (-2, 876543211), _PyTime_ROUND_DOWN), + (-1.1234567891, (-2, 876543210), _PyTime_ROUND_DOWN), + # Round away from zero + (0, (0, 0), _PyTime_ROUND_UP), + (-1, (-1, 0), _PyTime_ROUND_UP), + (-1.0, (-1, 0), _PyTime_ROUND_UP), + (1e-9, (0, 1), _PyTime_ROUND_UP), + (1e-10, (0, 1), _PyTime_ROUND_UP), + (-1e-9, (-1, 999999999), _PyTime_ROUND_UP), + (-1e-10, (-1, 999999999), _PyTime_ROUND_UP), + (-1.2, (-2, 800000000), _PyTime_ROUND_UP), + (0.9999999999, (1, 0), _PyTime_ROUND_UP), + (1.1234567890, (1, 123456790), _PyTime_ROUND_UP), + (1.1234567899, (1, 123456790), _PyTime_ROUND_UP), + (-1.1234567890, (-2, 876543211), _PyTime_ROUND_UP), + (-1.1234567891, (-2, 876543210), _PyTime_ROUND_UP), ): - self.assertEqual(pytime_object_to_timespec(obj), timespec) + with self.subTest(obj=obj, round=rnd, timespec=timespec): + self.assertEqual(pytime_object_to_timespec(obj, rnd), timespec) + rnd = _PyTime_ROUND_DOWN for invalid in self.invalid_values: - self.assertRaises(OverflowError, pytime_object_to_timespec, invalid) + self.assertRaises(OverflowError, + pytime_object_to_timespec, invalid, rnd) @unittest.skipUnless(time._STRUCT_TM_ITEMS == 11, "needs tm_zone support") def test_localtime_timezone(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -25,6 +25,9 @@ Library ------- +- Issue #20320: select.select() and select.kqueue.control() now round the + timeout aways from zero, instead of rounding towards zero. + - Issue #20616: Add a format() method to tracemalloc.Traceback. - Issue #19744: the ensurepip installation step now just prints a warning to diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -2459,7 +2459,7 @@ struct tm *tm; time_t t; - if (_PyTime_ObjectToTime_t(obj, &t) == -1) + if (_PyTime_ObjectToTime_t(obj, &t, _PyTime_ROUND_DOWN) == -1) return NULL; tm = localtime(&t); @@ -4127,7 +4127,7 @@ time_t timet; long us; - if (_PyTime_ObjectToTimeval(timestamp, &timet, &us) == -1) + if (_PyTime_ObjectToTimeval(timestamp, &timet, &us, _PyTime_ROUND_DOWN) == -1) return NULL; return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo); } diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2516,14 +2516,27 @@ return PyLong_FromLong(r); } +static int +check_time_rounding(int round) +{ + if (round != _PyTime_ROUND_DOWN && round != _PyTime_ROUND_UP) { + PyErr_SetString(PyExc_ValueError, "invalid rounding"); + return -1; + } + return 0; +} + static PyObject * test_pytime_object_to_time_t(PyObject *self, PyObject *args) { PyObject *obj; time_t sec; - if (!PyArg_ParseTuple(args, "O:pytime_object_to_time_t", &obj)) + int round; + if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_time_t", &obj, &round)) return NULL; - if (_PyTime_ObjectToTime_t(obj, &sec) == -1) + if (check_time_rounding(round) < 0) + return NULL; + if (_PyTime_ObjectToTime_t(obj, &sec, round) == -1) return NULL; return _PyLong_FromTime_t(sec); } @@ -2534,9 +2547,12 @@ PyObject *obj; time_t sec; long usec; - if (!PyArg_ParseTuple(args, "O:pytime_object_to_timeval", &obj)) + int round; + if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_timeval", &obj, &round)) return NULL; - if (_PyTime_ObjectToTimeval(obj, &sec, &usec) == -1) + if (check_time_rounding(round) < 0) + return NULL; + if (_PyTime_ObjectToTimeval(obj, &sec, &usec, round) == -1) return NULL; return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec); } @@ -2547,9 +2563,12 @@ PyObject *obj; time_t sec; long nsec; - if (!PyArg_ParseTuple(args, "O:pytime_object_to_timespec", &obj)) + int round; + if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_timespec", &obj, &round)) return NULL; - if (_PyTime_ObjectToTimespec(obj, &sec, &nsec) == -1) + if (check_time_rounding(round) < 0) + return NULL; + if (_PyTime_ObjectToTimespec(obj, &sec, &nsec, round) == -1) return NULL; return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec); } diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -4901,9 +4901,9 @@ } utime.now = 0; if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), - &a_sec, &a_nsec) == -1 || + &a_sec, &a_nsec, _PyTime_ROUND_DOWN) == -1 || _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), - &m_sec, &m_nsec) == -1) { + &m_sec, &m_nsec, _PyTime_ROUND_DOWN) == -1) { goto exit; } utime.atime_s = a_sec; diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -214,7 +214,8 @@ else { #ifdef MS_WINDOWS time_t sec; - if (_PyTime_ObjectToTimeval(tout, &sec, &tv.tv_usec) == -1) + if (_PyTime_ObjectToTimeval(tout, &sec, &tv.tv_usec, + _PyTime_ROUND_UP) == -1) return NULL; assert(sizeof(tv.tv_sec) == sizeof(long)); #if SIZEOF_TIME_T > SIZEOF_LONG @@ -229,7 +230,8 @@ /* 64-bit OS X has struct timeval.tv_usec as an int (and thus still 4 bytes as required), but no longer defined by a long. */ long tv_usec; - if (_PyTime_ObjectToTimeval(tout, &tv.tv_sec, &tv_usec) == -1) + if (_PyTime_ObjectToTimeval(tout, &tv.tv_sec, &tv_usec, + _PyTime_ROUND_UP) == -1) return NULL; tv.tv_usec = tv_usec; #endif @@ -2037,8 +2039,8 @@ ptimeoutspec = NULL; } else if (PyNumber_Check(otimeout)) { - if (_PyTime_ObjectToTimespec(otimeout, - &timeout.tv_sec, &timeout.tv_nsec) == -1) + if (_PyTime_ObjectToTimespec(otimeout, &timeout.tv_sec, + &timeout.tv_nsec, _PyTime_ROUND_UP) == -1) return NULL; if (timeout.tv_sec < 0) { diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -799,7 +799,8 @@ &signals, &timeout)) return NULL; - if (_PyTime_ObjectToTimespec(timeout, &tv_sec, &tv_nsec) == -1) + if (_PyTime_ObjectToTimespec(timeout, &tv_sec, &tv_nsec, + _PyTime_ROUND_DOWN) == -1) return NULL; buf.tv_sec = tv_sec; buf.tv_nsec = tv_nsec; diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -193,7 +193,7 @@ if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) return NULL; - if (_PyTime_ObjectToTimespec(obj, &tv_sec, &tv_nsec) == -1) + if (_PyTime_ObjectToTimespec(obj, &tv_sec, &tv_nsec, _PyTime_ROUND_DOWN) == -1) return NULL; tp.tv_sec = tv_sec; tp.tv_nsec = tv_nsec; @@ -341,7 +341,7 @@ whent = time(NULL); } else { - if (_PyTime_ObjectToTime_t(ot, &whent) == -1) + if (_PyTime_ObjectToTime_t(ot, &whent, _PyTime_ROUND_DOWN) == -1) return 0; } *pwhen = whent; diff --git a/Python/pytime.c b/Python/pytime.c --- a/Python/pytime.c +++ b/Python/pytime.c @@ -152,7 +152,7 @@ static int _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, - double denominator) + double denominator, _PyTime_round_t round) { assert(denominator <= LONG_MAX); if (PyFloat_Check(obj)) { @@ -167,6 +167,20 @@ intpart -= 1.0; } + floatpart *= denominator; + if (round == _PyTime_ROUND_UP) { + if (intpart >= 0) { + floatpart = ceil(floatpart); + if (floatpart >= denominator) { + floatpart = 0.0; + intpart += 1.0; + } + } + else { + floatpart = floor(floatpart); + } + } + *sec = (time_t)intpart; err = intpart - (double)*sec; if (err <= -1.0 || err >= 1.0) { @@ -174,7 +188,6 @@ return -1; } - floatpart *= denominator; *numerator = (long)floatpart; return 0; } @@ -188,12 +201,18 @@ } int -_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec) +_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round) { if (PyFloat_Check(obj)) { double d, intpart, err; d = PyFloat_AsDouble(obj); + if (round == _PyTime_ROUND_UP) { + if (d >= 0) + d = ceil(d); + else + d = floor(d); + } (void)modf(d, &intpart); *sec = (time_t)intpart; @@ -213,15 +232,17 @@ } int -_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec) +_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec, + _PyTime_round_t round) { - return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9); + return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round); } int -_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec) +_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec, + _PyTime_round_t round) { - return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6); + return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round); } void -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Feb 17 09:16:13 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 17 Feb 2014 09:16:13 +0100 Subject: [Python-checkins] Daily reference leaks (180e4b678003): sum=0 Message-ID: results for 180e4b678003 on branch "default" -------------------------------------------- test_site leaked [0, 2, -2] references, sum=0 test_site leaked [0, 2, -2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogIYoTAR', '-x'] From python-checkins at python.org Mon Feb 17 10:56:14 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 17 Feb 2014 10:56:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320652=3A_asyncio_?= =?utf-8?q?doc=3A_close_the_event_loop_in_run=5Fforever=28=29_example=2E_F?= =?utf-8?q?ix?= Message-ID: <3fSLDt3XqHz7LjT@mail.python.org> http://hg.python.org/cpython/rev/ea4c74cc4da5 changeset: 89231:ea4c74cc4da5 user: Victor Stinner date: Mon Feb 17 10:54:30 2014 +0100 summary: Close #20652: asyncio doc: close the event loop in run_forever() example. Fix also typo. Patch written by Vajrasky Kok. files: Doc/library/asyncio-task.rst | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -229,7 +229,7 @@ @asyncio.coroutine def slow_operation(future): yield from asyncio.sleep(1) - future.set_result('Future in done!') + future.set_result('Future is done!') loop = asyncio.get_event_loop() future = asyncio.Future() @@ -261,7 +261,7 @@ @asyncio.coroutine def slow_operation(future): yield from asyncio.sleep(1) - future.set_result('Future in done!') + future.set_result('Future is done!') def got_result(future): print(future.result()) @@ -271,7 +271,10 @@ future = asyncio.Future() asyncio.Task(slow_operation(future)) future.add_done_callback(got_result) - loop.run_forever() + try: + loop.run_forever() + finally: + loop.close() In this example, the future is responsible to display the result and to stop the loop. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 17 22:46:09 2014 From: python-checkins at python.org (larry.hastings) Date: Mon, 17 Feb 2014 22:46:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?release=3A_Added_my_hacked-up_release?= =?utf-8?q?_management_tools_for_3=2E4=2C_for_posterity=2E?= Message-ID: <3fSf015WXWz7LjV@mail.python.org> http://hg.python.org/release/rev/87189766b0cf changeset: 71:87189766b0cf user: Larry Hastings date: Mon Feb 17 13:46:12 2014 -0800 summary: Added my hacked-up release management tools for 3.4, for posterity. files: 3.4/README.txt | 12 + 3.4/dryparse/dryparse.py | 1398 ++++++++++++++++++++++++++ 3.4/threefourtool.py | 560 ++++++++++ 3 files changed, 1970 insertions(+), 0 deletions(-) diff --git a/3.4/README.txt b/3.4/README.txt new file mode 100644 --- /dev/null +++ b/3.4/README.txt @@ -0,0 +1,12 @@ +The files here are not in a particularly usable state. +They assume that you have a directory called + /home/larry/src/python/3.4 +which is a checkout of Python trunk with a named branch +called "3.4" (starting at revision e64ae8b82672). + +However, they do document the process used for making +3.4.0 rc2 and 3.4.0 final, and should be a good starting +point for a more general-purpose (and less hacked-up) tool. + + --Larry Hastings, release manager for Python 3.4 + 2014/02/17 diff --git a/3.4/dryparse/dryparse.py b/3.4/dryparse/dryparse.py new file mode 100755 --- /dev/null +++ b/3.4/dryparse/dryparse.py @@ -0,0 +1,1398 @@ +#!/usr/bin/env python3 +# +# dryparse +# +# A don't-repeat-yourself command-line parser. +# +# TODO: +# * rename value_usage +# * when called as a module (python3 -m dryparse ) it decorates +# the callables so that for all arguments it tries eval, and if +# that works it uses the result, otherwise it fails over to str +# * --version? +# * -h / --help ? +# * in usage: square brackets around optional options/arguments [-h] +# * in usage: angle brackets around positional arguments +# * python ideas: +# a typeerror should have an optional iterable of base classes of +# types it accepts +# +# +# License +# ======= +# +# Copyright 2012-2013 Larry Hastings +# +# This software is provided 'as-is', without any express or implied +# warranty. In no event will the authors be held liable for any damages +# arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, +# including commercial applications, and to alter it and redistribute it +# freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not +# claim that you wrote the original software. If you use this software +# in a product, an acknowledgment in the product documentation would be +# appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be +# misrepresented as being the original software. +# +# 3. This notice may not be removed or altered from any source +# distribution. +# + + +import collections +import inspect +import itertools +import shlex +import sys +import textwrap +import types +import unittest + +__all__ = [] +def all(fn): + __all__.append(fn) + return fn + +class Unspecified: + def __repr__(self): + return '' + def __bool__(self): + return False + +unspecified = Unspecified() + +def option_value_usage_formatter(name): + return " " + name.upper() + + + +def column_wrapper(prefix, words, *, + min_column=12, max_column=40, right_margin=79): + """ + Formats text in a pleasing format. + + "prefix" can be either a string or an iterable of strings. + + "words" should be an iterable of strings that have + already been broken up at word boundaries. + An empty string in the words iterable inserts + a newline in the output. () + + The output looks something like this: + + prefix here words here which are wrapped to + multiple lines in a pleasing way. + """ + + lines = [] + line_prefixes = [] + + if isinstance(prefix, str): + line = prefix + else: + prefixes = list(reversed(prefix)) + line = '' + indent = ' ' * 8 + add_space = False + while prefixes: + prefix = prefixes.pop() + test = line + if add_space: + test += ' ' + else: + add_space = True + test += prefix + if len(test) > right_margin: + prefixes.append(prefix) + lines.append(line) + line = indent + first = True + line = test + + if len(line) < max_column: + column = max(min_column, len(line)) + line += ' ' * (column - len(line)) + line_prefixes.append(line) + else: + column = max_column + lines.append(line) + + empty_prefixes = itertools.repeat(' ' * column) + prefixes = itertools.chain(line_prefixes, empty_prefixes) + words = list(reversed(words)) + + if not words: + for prefix in line_prefixes: + lines.append(prefix) + + while words: + test = line = next(prefixes) + is_first_word = True + while words: + o = words.pop() + if not o: + break + spacer = ' ' if line.endswith('.') else ' ' + test = line + spacer + o + if len(test) > right_margin: + if is_first_word: + line = test + else: + words.append(o) + break + else: + line = test + is_first_word = False + lines.append(line) + + return '\n'.join(lines).rstrip() + + +class _column_wrapper_splitter: + + def __init__(self, tab_width): + self.next(self.state_initial) + self.words = [] + self.hopper = [] + self.emit = self.hopper.append + self.col = self.next_col = 0 + self.line = self.next_line = 0 + + def newline(self): + assert not self.hopper, "Emitting newline while hopper is not empty!" + self.words.append('') + + def empty_hopper(self): + if self.hopper: + self.words.append(''.join(self.hopper)) + self.hopper.clear() + + def next(self, state, c=None): + self.state = state + if c is not None: + self.state(c) + + def write(self, c): + if c in '\t\n': + if c == '\t': + self.next_col = col + tab_width - (col % tab_width) + else: + self.next_col = 0 + self.next_line = self.line + 1 + else: + self.next_col = self.col + 1 + + self.state(c) + + self.col = self.next_col + self.line = self.next_line + + def close(self): + self.empty_hopper() + + def state_paragraph_start(self, c): + if c.isspace(): + return + if self.col >= 4: + next = self.state_code_line_start + else: + next = self.state_in_paragraph + self.next(next, c) + + state_initial = state_paragraph_start + + def state_code_line_start(self, c): + if c.isspace(): + if c == '\n': + self.newline() + self.next(self.state_paragraph_start) + return + if self.col < 4: + raise ValueError("Can't outdent past 4 in a code paragraph! (line " + str(self.line) + " col " + str(self.col) + ")") + self.emit(' ' * self.col) + self.next(self.state_in_code, c) + + def state_in_code(self, c): + if c.isspace(): + if c == '\n': + self.empty_hopper() + self.newline() + self.next(self.state_code_line_start) + else: + self.emit(' ' * (self.next_col - self.col)) + else: + self.emit(c) + + def state_paragraph_line_start(self, c): + if not c.isspace(): + return self.next(self.state_in_paragraph, c) + if c == '\n': + self.newline() + self.newline() + self.next(self.state_paragraph_start) + + def state_in_paragraph(self, c): + if not c.isspace(): + self.emit(c) + return + + self.empty_hopper() + if c == '\n': + self.next(self.state_paragraph_line_start) + + +def column_wrapper_split(s, *, tab_width=8): + """ + Splits up a string into individual words, suitable + for feeding into column_wrapper(). + + Paragraphs indented by four spaces or more preserve + whitespace; internal whitespace is preserved, and the + newline is preserved. (This is for code examples.) + + Paragraphs indented by less than four spaces will be + broken up into individual words. + """ + cws = _column_wrapper_splitter(tab_width) + for c in s: + cws.write(c) + cws.close() + return cws.words + + + at all +class DryArgument: + type = None + doc = None + multiple = False + value = unspecified + value_usage = None + + def __repr__(self): + a = ['') + return ''.join(a) + + def usage(self, *, first_line=True): + if not self.options: + return name + a = [] + add = a.append + + if first_line: + add('[') + separator = '|' + else: + separator = ', ' + + add_separator = False + for name in sorted(self.options): + if add_separator: + add(separator) + else: + add_separator = True + add('-') + if len(name) > 1: + add('-') + add(name) + if self.type != bool: + add('=') + add(self.value_usage) + if first_line: + add(']') + return ''.join(a) + + def set_value(self, value): + value = self.type(value) + if self.multiple: + self.value.append(value) + else: + self.value = value + + def __init__(self, name, default, annotations, *, is_option=False): + self.name = name + self.default = default + self.options = set() + if is_option: + self.options.add(name) + + for a in annotations or (): + if callable(a): + assert self.type is None + self.type = a + continue + if isinstance(a, str): + if a.startswith('-'): + assert is_option, "positional argument " + repr(name) + " cannot be an option (only kwonly arguments can be options)" + # options + for option in a.strip().split(): + if option == '*': + assert self.default is unspecified, "You can't specify a default for an option that accepts multiple values. (" + repr(name) + ")" + self.value = self.default = [] + self.multiple = True + continue + if option.startswith('='): + self.value_usage = option[1:] + if option in {'-', '--'}: + continue + assert option.startswith('-'), "Illegal field in annotation list of options: '" + option + "'" + assert (len(option) == 2) or (option.startswith('--')), "Illegal field in annotation list of options: '" + option + "', but only single-letter options can use one dash" + stripped = option.lstrip('-') + assert stripped not in self.options, "Option '" + option + "' specified more than once!" + self.options.add(stripped) + else: + assert self.doc is None + self.doc = a + continue + assert None, "Unknown annotation for " + name + + if self.type is None: + valid_default = self.default is not unspecified + inferred = type(self.default) if valid_default else None + default_type = bool if self.options else str + + self.type = inferred or default_type + + if self.default is unspecified and self.options: + self.default = self.type() + + if is_option and (self.type is not bool) and (not self.value_usage): + self.value_usage = option_value_usage_formatter(self.type.__name__) + + +class OptionError(RuntimeError): + pass + + at all +class DryCommand: + + def __repr__(self): + a = [' '] + add = a.append + + [add(option) for option in self.options] + + add('>') + return ''.join(a) + + has_options = has_arguments = False + + def __init__(self, name, callable): + self.name = name + self.callable = callable + self.options = {} + self.all_arguments = [] + self.arguments = [] + self.doc = callable.__doc__ or '' + self.star_args = None + + try: + i = inspect.getfullargspec(callable) + except TypeError: + sys.exit("Can't add " + repr(name) + ", callable isn't introspectable " + repr(callable)) + if isinstance(callable, types.MethodType): + i.args.pop(0) + + # i.defaults is kind of silly + # convert it to a straight-up tuple + # with unspecified for unspecified fields + if i.defaults is None: + defaults = (unspecified,) * len(i.args) + else: + defaults = ((unspecified,) * (len(i.args) - len(i.defaults))) + i.defaults + + def add(name, default, i, *, is_option=False): + argument = DryArgument(name, default, i.annotations.get(name), is_option=is_option) + self.all_arguments.append(argument) + assert int(is_option) ^ (not int(bool(argument.options))) + if argument.options: + for option in argument.options: + assert option not in self.options + self.options[option] = argument + self.has_options = True + else: + self.arguments.append(argument) + self.has_arguments = True + + for name, default in zip(i.args, defaults): + add(name, default, i, is_option=False) + + if i.varargs: + self.star_args = DryArgument(i.varargs, unspecified, i.annotations.get(i.varargs)) + self.has_arguments = True + + kwonlydefaults = i.kwonlydefaults or {} + for name in i.kwonlyargs or (): + default = kwonlydefaults.get(name, unspecified) + add(name, default, i, is_option=True) + + def _usage_first_line(self, global_handler): + """ + Everything after the command name. + """ + + def format_options_for_first_line(command): + if not command: + return [] + + seen = set() + + short_options = [] + long_options = [] + for name in sorted(command.options): + value = command.options[name] + if value in seen: + continue + if (len(value.options) == 1 and + value.type is bool and + len(name) == 1): + short_options.append(name) + else: + long_options.append(value.usage(first_line=True)) + seen.add(value) + + if short_options: + long_options.insert(0, '[-' + ''.join(short_options) + ']') + return long_options + + global_options = format_options_for_first_line(global_handler) + options = format_options_for_first_line(self) + + arguments = [] + unwind = 0 + for argument in self.arguments: + if argument.default is not unspecified: + arguments.append('[') + unwind += 1 + arguments.append(argument.name) + + if self.star_args: + arguments.append('[...]') + + arguments.append(']' * unwind) + + prefix = ["Usage:", sys.argv[0]] + prefix.extend(global_options) + prefix.append(self.name) + + words = [] + words.extend(options) + words.extend(arguments) + + return column_wrapper(prefix, words) + + def _usage(self, *, global_handler=None, short=False, error=None): + short = bool(short or error) + output = [] + def print(*a): + s = " ".join([str(x) for x in a]) + output.append(s) + lines = [] + summary_line = '' + if self.doc: + lines = [x.rstrip() for x in textwrap.dedent(self.doc.expandtabs()).split('\n')] + while lines and not lines[0]: + del lines[0] + if lines: + summary_line = lines[0] + del lines[0] + while lines and not lines[0]: + del lines[0] + while lines and not lines[-1].lstrip(): + lines.pop() + + if error: + print(error) + + print(self._usage_first_line(global_handler)) + + if error or short: + print('Try "' + sys.argv[0] + ' help ' + self.name + '" for more information.') + return '\n'.join(output) + + print() + print(summary_line) + + # global options + if global_handler: + options = {} + longest_option = 0 + for argument in global_handler.all_arguments: + if argument.options: + dashed_options = [ '-' + ('-' if len(option) > 1 else '') + option for option in argument.options] + all_options = ', '.join(sorted(dashed_options)) + longest_option = max(longest_option, len(all_options)) + options[all_options] = argument + print() + print("Global options:") + min_column = longest_option + 4 + for all_options in sorted(options): + argument = options[all_options] + prefix = " " + all_options + split_doc = column_wrapper_split(argument.doc) + formatted = column_wrapper(prefix, split_doc, min_column=min_column) + print(formatted) + + options = {} + longest_option = longest_positional = 0 + for argument in self.all_arguments: + if argument.options: + dashed_options = [ '-' + ('-' if len(option) > 1 else '') + option for option in argument.options] + all_options = ', '.join(sorted(dashed_options)) + longest_option = max(longest_option, len(all_options)) + options[all_options] = argument + else: + longest_positional = max(longest_positional, len(argument.name)) + if abs(longest_positional - longest_option) < 3: + longest_positional = longest_option = max(longest_positional, longest_option) + if options: + print() + print("Options:") + min_column = longest_option + 4 + for all_options in sorted(options): + argument = options[all_options] + prefix = " " + all_options + split_doc = column_wrapper_split(argument.doc or '') + formatted = column_wrapper(prefix, split_doc, min_column=min_column) + print(formatted) + if self.arguments: + print() + print("Arguments:") + min_column = longest_positional + 2 + for argument in self.arguments: + prefix = " " + argument.name + split_doc = column_wrapper_split(argument.doc or '') + formatted = column_wrapper(prefix, split_doc, min_column=min_column) + print(formatted) + if self.star_args: + print(" [" + self.star_args.name + "...]") + + if lines: + print() + for line in lines: + print(" ", line) + + return '\n'.join(output) + + def usage(self, *, error=None): + print(self._usage(error=error)) + + def __call__(self, argv, return_arguments=False): + seen = set() + needs_value = None + + def analyze_option(option): + argument = self.options[option] + return argument, argument.type is bool + + def handle_option(option, value): + nonlocal self + nonlocal needs_value + argument, is_bool = analyze_option(option) + if is_bool: + argument.value = not argument.value + else: + if value is unspecified: + needs_value = argument + else: + argument.set_value(value) + seen.add(option) + + arguments = [] + all_positional = False + while argv: + a = argv.pop(0) + if all_positional: + arguments.append(a) + continue + if needs_value: + needs_value.set_value(a) + needs_value = None + continue + if a == '--': + all_positional = True + continue + if a.startswith('-'): + if '=' in a: + a, _, value = a.partition('=') + a = a.strip() + value = value.strip() + assert a.startswith('--') or (len(a) == 2), "string " + repr(a) + " isn't double-dash nor -x" + else: + value = unspecified + if a.startswith('--'): + option = a[2:] + if option not in self.options: + raise OptionError('Unknown option "' + a + '".') + handle_option(option, value) + else: + single_letters = [] + for c in a[1:]: + if c not in self.options: + raise OptionError('Unknown option "' + a + '".') + arg, is_bool = analyze_option(c) + single_letters.append([c, unspecified]) + if not is_bool: + break + remaining = a[len(single_letters)+1:] + if remaining or (value is not unspecified): + remaining_str = "".join(remaining) + if value is not unspecified: + if remaining_str: + remaining_str += '=' + value + else: + remaining_str = value + single_letters[-1][1] = remaining_str + for c, value in single_letters: + handle_option(c, value) + continue + arguments.append(a) + + star_args = [] + if not return_arguments: + i = -1 + for i, (argument, a) in enumerate(zip(self.arguments, arguments)): + t = argument.type or str + argument.value = t(a) + if self.star_args: + t = self.star_args.type + star_args = [t(x) for x in arguments[i + 1:]] + + final_kwargs = {} + final_args = [] + for a in self.all_arguments: + if a.value == unspecified: + a.value = a.default + if a.options: + final_kwargs[a.name] = a.value + else: + final_args.append(a.value) + if star_args: + final_args.extend(star_args) + + # print("DEEBUG EENFO:") + # print("argv", argv) + # for i, a in enumerate(self.all_arguments): + # print("all_arguments[", i, '] =', a) + # print("final_args", final_args) + # print("final_kwargs", final_kwargs) + + needed = len(list(filter(lambda x: x == unspecified, final_args))) + if needed: + specified = len(arguments) + error = ["Not enough arguments."] + if specified: + error.extend((" " + str(specified + needed), "required, but only", str(specified), "specified.")) + return self.usage(error=" ".join(error)) + assert unspecified not in final_args + + return_value = self.callable(*final_args, **final_kwargs) + if return_arguments: + return arguments + return return_value + + at all +def ignore(callable): + callable.__dryparse_use__ = False + return callable + + at all +def command(callable): + callable.__dryparse_use__ = True + return callable + + + at all +class DryParse: + + def __init__(self): + self.commands = {} + self.doc = "" + self.add(self.help, "help") + + _global_handler = None + + @property + def global_handler(self): + return self._global_handler + + @global_handler.setter + def global_handler(self, value): + if not isinstance(value, DryCommand): + value = DryCommand('', value) + self._global_handler = value + + def add_raw(self, o, name=None): + assert callable(o) + name = name or o.__name__ + self.commands[name] = o + + def add(self, o, name=None): + assert callable(o) + name = name or o.__name__ + self.commands[name] = DryCommand(name, o) + + def __setitem__(self, name, value): + self.add(name, value) + + def test(self, o, name=None): + if not callable(o): + return False + + # if it's been explicitly labeled, obey that + value = getattr(o, '__dryparse_use__', None) + if value is not None: + return value + + # * no if it starts and ends with '__' + name = name or o.__name__ + if name.startswith('_'): + return False + + return None + + def update(self, o, test=None, default=None): + if o is None: + return + + test = test or self.test + + def NoneToTrue(value): + if value is None: + return True + return value + + if isinstance(o, collections.Mapping): + if default is None: + default = True + for name, value in o.items(): + if NoneToTrue(test(value, name=name)): + self.add(value, name=name) + return + + if isinstance(o, collections.Iterable): + if default is None: + default = True + for value in o: + if NoneToTrue(test(value)): + self.add(value) + return + + def NoneToFalse(value): + if value is None: + return True + return value + + for name in dir(o): + value = getattr(o, name) + if NoneToFalse(test(value, name)): + self.add(value, name=name) + + def usage(self, *, argv=(), error=None): + print(self._usage(argv=argv, error=error)) + + def _usage(self, *, argv=(), error=None): + output = [] + def print(*a): + output.append(' '.join(str(x) for x in a)) + + assert not (argv and error) + if error: + print(error) + if argv: + command = argv[0] + if command not in self.commands: + return self.usage(error="Unknown command " + repr(command)) + if command == 'help': + return self.usage() + return self.commands[command]._usage() + + have_global_options = self.global_handler and self.global_handler.options + have_commands = self.commands + have_global_arguments = (not have_commands) and self.global_handler and self.global_handler.have_arguments + have_options = any(command.has_options for command in self.commands.values()) + have_arguments = any(command.has_arguments for command in self.commands.values()) + + a = ["Usage:", sys.argv[0]] + add = a.append + if have_global_options: + add("[options]") + if have_global_arguments: + add("arguments") + if have_commands: + add("command") + if have_options: + add("[options]") + if have_arguments: + add("[arguments ...]") + print(' '.join(a)) + if self.commands: + print('Try "' + sys.argv[0] + ' help" for a list of commands.') + + return '\n'.join(output) + + def print_commands(self): + if not self.commands: + return + print("Supported commands:") + commands = sorted(self.commands) + longest = len('help') + for name in commands: + longest = max(longest, len(name)) + for name in commands: + if name == 'help': + print(" ", "help".ljust(longest), " List all commands, or show usage on a specific command.") + continue + command = self.commands[name] + first_line = command.doc.strip().split('\n')[0].strip() + print(" ", name.ljust(longest), "", first_line) + + def help(self, command=''): + if command and (command != 'help'): + if command in self.commands: + return self.commands[command]._usage(global_handler=self.global_handler) + print('Unknown command "' + command + '".') + print() + self.print_commands() + print() + print('Use "' + sys.argv[0] + ' help command" for help on a specific command.') + + def main(self, argv=None): + return_value = None + if argv == None: + argv = sys.argv[1:] + + if self.global_handler: + have_commands = bool(self.commands) + if have_commands: + global_argv = [] + while argv and argv[0].startswith('-'): + global_argv.append(argv.pop(0)) + else: + global_argv = argv + + if global_argv: + try: + return_value = self.global_handler(global_argv, return_arguments=have_commands) + except OptionError as e: + # try to find the command + command = None + for s in argv: + if s.startswith('-'): + continue + command = self.commands.get(s, None) + break + + if command: + return command.usage(error=str(e)) + return self.usage(error=str(e)) + + if have_commands: + argv = return_value + else: + return return_value + + if not self.commands: + return return_value + + if not argv: + return self.usage(error="No command specified.") + + command_str = argv.pop(0) + command = self.commands.get(command_str, None) + if not command: + if command_str == "help": + return self.usage(argv=argv) + return self.usage(error="Command " + repr(command_str) + " not recognized.") + try: + return command(argv) + except OptionError as e: + return command.usage(error=str(e)) + + +class UnitTests(unittest.TestCase): + + def setUp(self): + class Commands: + pass + self.C = Commands + self.c = Commands() + self.dp = DryParse() + + def add(self, callable): + name = callable.__name__ + setattr(self.C, name, callable) + self.dp.add(getattr(self.c, name)) + + def main(self, cmdline): + split = shlex.split(cmdline) + self.dp.main(split) + + def test_basics(self): + c = self.c + dp = self.dp + self.assertTrue('command1' not in dp._usage()) + self.assertTrue('command2' not in dp._usage()) + def command1(self, a, b): + self.a = a + self.b = b + self.add(command1) + self.assertTrue('command1' in dp._usage()) + self.assertTrue('command2' not in dp._usage()) + def command2(self, a, b): + self.a = a + self.b = b + self.add(command2) + self.assertTrue('command1' in dp._usage()) + self.assertTrue('command2' in dp._usage()) + c.a = c.b = 0 + self.main('command1 22 33') + self.assertEqual(c.a, '22') + self.assertEqual(c.b, '33') + + def test_function_docs(self): + def command(self, a): + "box turtle" + pass + self.add(command) + self.assertTrue('box turtle' in self.dp._usage()) + + def test_argument_docs(self): + def command3(self, a:{'lagomorph'}): + pass + self.add(command3) + self.assertTrue('lagomorph' in self.dp._usage(argv=['command3'])) + + def test_callable_annotations(self): + def cast_fn(s=None): + return 12345 + def callable_annotations(self, a:{cast_fn}=11111): + self.value = a + + def reset(): + self.c.value = None + self.add(callable_annotations) + + reset() + self.main('callable_annotations abc') + self.assertEqual(self.c.value, 12345) + + reset() + self.main('callable_annotations') + self.assertEqual(self.c.value, 11111) + + def test_long_dashed_annotations(self): + def long_dashed_annotations(self, a, *, debug): + self.debug = debug + self.a = a + + def reset(): + self.c.debug = self.c.a = None + self.add(long_dashed_annotations) + + reset() + self.main('long_dashed_annotations abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.debug, False) + reset() + self.main('long_dashed_annotations --debug def') + self.assertEqual(self.c.a, 'def') + self.assertEqual(self.c.debug, True) + reset() + self.main('long_dashed_annotations ghi') + self.assertEqual(self.c.a, 'ghi') + self.assertEqual(self.c.debug, False) + + def test_short_dashed_annotations(self): + def test_short_dashed_annotations(self, a, *, n, q): + self.a = a + self.n = n + self.q = q + def reset(): + self.c.a = self.c.n = self.c.q = None + self.dp.commands = {} + self.add(test_short_dashed_annotations) + reset() + self.main('test_short_dashed_annotations abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.n, False) + self.assertEqual(self.c.q, False) + reset() + self.main('test_short_dashed_annotations -q ducks') + self.assertEqual(self.c.a, 'ducks') + self.assertEqual(self.c.n, False) + self.assertEqual(self.c.q, True) + reset() + self.main('test_short_dashed_annotations -n garofalo') + self.assertEqual(self.c.a, 'garofalo') + self.assertEqual(self.c.n, True) + self.assertEqual(self.c.q, False) + reset() + self.main('test_short_dashed_annotations -nq sassy') + self.assertEqual(self.c.a, 'sassy') + self.assertEqual(self.c.n, True) + self.assertEqual(self.c.q, True) + reset() + self.main('test_short_dashed_annotations -qn boots') + self.assertEqual(self.c.a, 'boots') + self.assertEqual(self.c.n, True) + self.assertEqual(self.c.q, True) + + def test_short_dashed_with_value(self): + def short_dashed_with_value(self, a, *, n:{int}, q:{int}): + self.a = a + self.n = n + self.q = q + + def reset(): + self.dp.commands = {} + self.c.a = self.c.b = self.c.n = self.c.q = None + self.add(short_dashed_with_value) + + + reset() + self.main('short_dashed_with_value abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.n, 0) + self.assertEqual(self.c.q, 0) + + reset() + self.main('short_dashed_with_value -n=5 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.n, 5) + self.assertEqual(self.c.q, 0) + + reset() + self.main('short_dashed_with_value -n 5 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.n, 5) + self.assertEqual(self.c.q, 0) + + reset() + self.main('short_dashed_with_value -n5 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.n, 5) + self.assertEqual(self.c.q, 0) + + reset() + self.main('short_dashed_with_value -q=3 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.n, 0) + self.assertEqual(self.c.q, 3) + + reset() + self.main('short_dashed_with_value -q 3 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.n, 0) + self.assertEqual(self.c.q, 3) + + reset() + self.main('short_dashed_with_value -q 3 -n=5 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.n, 5) + self.assertEqual(self.c.q, 3) + + reset() + def short_dashed_with_value_2(self, *, a, b, n:{int}=0): + self.a = a + self.b = b + self.n = n + self.add(short_dashed_with_value_2) + self.main("short_dashed_with_value_2 -ban5") + self.assertEqual(self.c.a, True) + self.assertEqual(self.c.b, True) + self.assertEqual(self.c.n, 5) + + def test_long_dashed_with_value(self): + def long_dashed_with_value(self, a, *, debug:{int}=0, quiet:{int}=0): + self.a = a + self.debug = debug + self.quiet = quiet + + def reset(): + self.c.a = self.c.debug = self.c.quiet = None + self.add(long_dashed_with_value) + + reset() + self.main('long_dashed_with_value abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.debug, 0) + self.assertEqual(self.c.quiet, 0) + + reset() + self.main('long_dashed_with_value --debug=5 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.debug, 5) + self.assertEqual(self.c.quiet, 0) + + reset() + self.main('long_dashed_with_value --debug 5 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.debug, 5) + self.assertEqual(self.c.quiet, 0) + + reset() + self.main('long_dashed_with_value --quiet=3 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.debug, 0) + self.assertEqual(self.c.quiet, 3) + + reset() + self.main('long_dashed_with_value --quiet 3 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.debug, 0) + self.assertEqual(self.c.quiet, 3) + + reset() + self.main('long_dashed_with_value --quiet 3 --debug=5 abc') + self.assertEqual(self.c.a, 'abc') + self.assertEqual(self.c.debug, 5) + self.assertEqual(self.c.quiet, 3) + + def test_multiple_options_as_boolean(self): + def reset(): + self.c.quiet = None + self.add(multiple_options_as_boolean) + + def multiple_options_as_boolean(self, *, quiet:{'-q --shut-up -x'}): + self.quiet = quiet + + reset() + self.main('multiple_options_as_boolean') + self.assertEqual(self.c.quiet, False) + reset() + self.main('multiple_options_as_boolean -q') + self.assertEqual(self.c.quiet, True) + reset() + self.main('multiple_options_as_boolean --quiet') + self.assertEqual(self.c.quiet, True) + reset() + self.main('multiple_options_as_boolean --shut-up') + self.assertEqual(self.c.quiet, True) + reset() + self.main('multiple_options_as_boolean -x') + self.assertEqual(self.c.quiet, True) + reset() + self.main('multiple_options_as_boolean') + self.assertEqual(self.c.quiet, False) + + def test_multiple_options_as_type(self): + def multiple_options_as_type(self, *, value:{'-v --thingy -y', str}='unset'): + self.value = value + + def reset(): + self.c.value = None + self.add(multiple_options_as_type) + + reset() + self.main('multiple_options_as_type') + self.assertEqual(self.c.value, 'unset') + + reset() + self.main('multiple_options_as_type -v 123') + self.assertEqual(self.c.value, '123') + reset() + self.main('multiple_options_as_type --value 456') + self.assertEqual(self.c.value, '456') + reset() + self.main('multiple_options_as_type --thingy 789') + self.assertEqual(self.c.value, '789') + reset() + self.main('multiple_options_as_type -y 101112') + self.assertEqual(self.c.value, '101112') + + reset() + self.main('multiple_options_as_type -v=123') + self.assertEqual(self.c.value, '123') + reset() + self.main('multiple_options_as_type --value=456') + self.assertEqual(self.c.value, '456') + reset() + self.main('multiple_options_as_type --thingy=789') + self.assertEqual(self.c.value, '789') + reset() + self.main('multiple_options_as_type -y=101112') + self.assertEqual(self.c.value, '101112') + + reset() + self.main('multiple_options_as_type') + self.assertEqual(self.c.value, 'unset') + + def test_double_dash(self): + """ + command -- -a -b -c + + -- means "all remaining arguments are positional parameters" + """ + def double_dash(self, a, b='optional', c='empty', *, q, debug): + self.a = a + self.b = b + self.c = c + self.q = q + self.debug = debug + + def reset(): + self.c.a = self.c.b = self.c.c = self.c.q = self.c.debug = None + self.add(double_dash) + + reset() + self.main('double_dash 1 2 3') + self.assertEqual(self.c.a, '1') + self.assertEqual(self.c.b, '2') + self.assertEqual(self.c.c, '3') + self.assertEqual(self.c.q, False) + self.assertEqual(self.c.debug, False) + + reset() + self.main('double_dash -q --debug 1') + self.assertEqual(self.c.a, '1') + self.assertEqual(self.c.b, 'optional') + self.assertEqual(self.c.c, 'empty') + self.assertEqual(self.c.q, True) + self.assertEqual(self.c.debug, True) + + reset() + self.main('double_dash -- -q --debug 1') + self.assertEqual(self.c.a, '-q') + self.assertEqual(self.c.b, '--debug') + self.assertEqual(self.c.c, '1') + self.assertEqual(self.c.q, False) + self.assertEqual(self.c.debug, False) + + def test_mixing_positional_arguments_and_options(self): + def mpaao(self, a:{int}, *, debug, quiet): + self.a = a + self.debug = debug + self.quiet = quiet + def reset(): + self.c.a = self.c.debug = self.c.quiet = None + self.add(mpaao) + + reset() + self.main('mpaao --debug 1') + self.assertEqual(self.c.a, 1) + self.assertEqual(self.c.debug, True) + self.assertEqual(self.c.quiet, False) + + reset() + self.main('mpaao 2 --debug') + self.assertEqual(self.c.a, 2) + self.assertEqual(self.c.debug, True) + self.assertEqual(self.c.quiet, False) + + reset() + self.main('mpaao --quiet 3 --debug') + self.assertEqual(self.c.a, 3) + self.assertEqual(self.c.debug, True) + self.assertEqual(self.c.quiet, True) + + reset() + self.main('mpaao 4 --quiet') + self.assertEqual(self.c.a, 4) + self.assertEqual(self.c.debug, False) + self.assertEqual(self.c.quiet, True) + + def test_star_args(self): + def star_args(self, a:{int}, *args): + self.a = a + self.args = args + + def reset(): + self.c.a = self.c.args = None + self.add(star_args) + + reset() + self.main('star_args 4') + self.assertEqual(self.c.a, 4) + self.assertEqual(self.c.args, ()) + + reset() + self.main('star_args 5 a b c') + self.assertEqual(self.c.a, 5) + self.assertEqual(self.c.args, ('a', 'b', 'c')) + + def star_args_2(self, a:{int}, *args:{int}): + self.a = a + self.args = args + self.add(star_args_2) + + self.main('star_args_2 5 6 7 8 9') + self.assertEqual(self.c.a, 5) + self.assertEqual(self.c.args, (6, 7, 8, 9)) + + def test_multiple_option(self): + self.dump = None + def command(self, *, dump:{'-d *', int}): + self.dump = dump + self.add(command) + + self.main('command -d 5 -d 6 -d 7') + self.assertEqual(self.c.dump, [5, 6, 7]) + + def test_global_options(self): + def glo(*, thingy:{str}='', silent:{'-s'}=False): + self.c.thingy = thingy + self.c.silent = silent + + def command1(self, a:{int}, b:{int}=1): + self.a = a + self.b = b + + def command2(self, a, b=''): + self.a = a + self.b = b + + def reset(): + self.c.a = self.c.b = self.c.thingy = self.c.silent = None + self.dp.global_handler = glo + self.add(command1) + self.add(command2) + + reset() + self.main('command1 3 5') + self.assertEqual(self.c.a, 3) + self.assertEqual(self.c.b, 5) + + reset() + self.main('command2 a b') + self.assertEqual(self.c.a, 'a') + self.assertEqual(self.c.b, 'b') + + reset() + self.main('--silent command1 99') + self.assertEqual(self.c.a, 99) + self.assertEqual(self.c.b, 1) + self.assertEqual(self.c.silent, True) + + reset() + self.main('--thingy=abc command2 xyz') + self.assertEqual(self.c.a, 'xyz') + self.assertEqual(self.c.b, '') + self.assertEqual(self.c.silent, False) + self.assertEqual(self.c.thingy, 'abc') + + + + +def eval_or_str(s): + try: + return eval(s, {}, {}) + except (NameError, SyntaxError): + return s + +if __name__ == "__main__": + sys.exit("no module functionality yet!") diff --git a/3.4/threefourtool.py b/3.4/threefourtool.py new file mode 100755 --- /dev/null +++ b/3.4/threefourtool.py @@ -0,0 +1,560 @@ +#!/usr/bin/env python3 + +import atexit +import collections +import datetime +from dryparse import dryparse +import os +import pprint +import pickle +import subprocess +import sys +import tempfile +import time + + +def line_to_rev(line): + if line.startswith("changeset:"): + line = line[len("changeset:"):].strip() + local, _, rev = line.strip().partition(':') + assert _ == ':' + rev = rev.strip() + assert rev.isalnum() + assert local.isdigit() + # print(repr(line), rev) + return local, rev + +changesets = collections.OrderedDict() +user_date_to_revs = {} # "user date" == "{user} {date}", maps to (rev, branch) +default_to_34 = {} # maps rev in default to rev in 3.4 +default_from_34 = {} # maps rev in 3.4 to rev in default +revs = [] +branches = {} + +def line_iterator(pipe, encoding='utf-8'): + text = b'' + while True: + got = pipe.read(4096) + if not got: + break + # print("GOT", repr(got)) + text += got + fields = text.split(b'\n') + text = fields.pop() + for line in fields: + # print("LINE YIELD", repr(line)) + yield line.decode(encoding) + if text: + # print("LINE YIELD LAST", repr(line)) + yield text.decode(encoding) + +def changeset_iterator(pipe): + i = line_iterator(pipe) + lines = [] + + for line in i: + if line.startswith("changeset: "): + break + else: + return + + lines.append(line) + for line in i: + if line.startswith("changeset: "): + # print("CS YIELD", lines) + yield "\n".join(lines) + lines = [line] + continue + lines.append(line) + assert lines + # print("CS YIELD LAST", lines) + yield "\n".join(lines) + +def get_user_date_to_revs(fields): + return user_date_to_revs[fields['user'] + ' ' + fields['date']] + +def read_changesets(earliest = '6343bdbb7085'): + if changesets: + return + + p = None + current_directory = os.getcwd() + try: + os.chdir("/home/larry/src/python/3.4") + p = subprocess.Popen(["/usr/bin/hg", "log"], stdout=subprocess.PIPE) + # with open("/home/larry/src/python/logtxt", "rt", encoding="utf-8") as f: + # output = f.read() + + fixup_parent = False + for c in changeset_iterator(p.stdout): + lines = c.split('\n') + # print("REV", end='') + local, rev = line_to_rev(lines[0]) + if fixup_parent: + # parents is still set to the previous rev's parents list! + parents.append(rev) + fixup_parent = False + in_description = False + description = [] + parents = [] + fields = {'description': description, 'parents': parents, 'local': local} + for line in lines[1:]: + if in_description: + description.append(line.strip()) + continue + line = line.strip() + if not line: + continue + field, _, text = line.partition(':') + assert _ == ':', "no colon in line: " + repr(line) + field = field.strip() + text = text.strip() + if field == 'parent': + # print("PARENT", end='') + parent = line_to_rev(text)[1] + parents.append(parent) + elif field == 'description': + in_description = True + if text: + description.append(text) + else: + fields[field] = text + # clean up description + fields['description'] = '\n'.join(description).strip().split('\n') + branch = fields.get('branch') + user = fields['user'] + date = fields['date'] + + changesets[rev] = fields + user_date = "{} {}".format(user, date) + if user_date not in user_date_to_revs: + user_date_to_revs[user_date] = set() + user_date_to_revs[user_date].add((rev, branch)) + revs.append(rev) + if not branch in branches: + branches[branch] = [] + branches[branch].append(rev) + if rev == earliest: + break + if not parents: + fixup_parent = True + + finally: + os.chdir(current_directory) + if p: + p.stdout.close() + for r in user_date_to_revs.values(): + d = dict((branch, rev) for rev, branch in r) + if '3.4' in d and None in d: + default_to_34[d[None]] = d["3.4"] + default_from_34[d['3.4']] = d[None] + +def header(category, printer): + print(category) + printer(""" +

{}

+ +""".format(category)) + +def footer(printer): + printer(""" +
+""") + + +def print_rev(rev, printer): + fields = changesets[rev] + d = dict(fields) + description = fields['description'] + d['rev'] = rev + d['description0'] = description[0] + d['description1+'] = "
\n".join(description[1:]) + print(" r", rev) + printer(""" + + + + +
{rev} + + + + +{user} + + + +{date} + + + +{description0} + + +""".format_map(d)) + + +def print_revs(print_test, lineage_test, printer): + seen = set() + + for rev, fields in changesets.items(): + print(" :", rev) + rev_to_print = print_test(rev) + if rev_to_print: + break + + print_rev(rev_to_print, printer) + seen.add(rev_to_print) + + hopper = [] + def refill_hopper(parents): + hopper.extend([(revs.index(r), r) for r in parents]) + hopper.sort() + + parents = fields['parents'] + print(" r", rev, "p", parents) + refill_hopper(parents) + while hopper: + _, rev = hopper.pop(0) + print(" ?", rev) + if not lineage_test(rev): + continue + fields = changesets[rev] + parents = fields['parents'] + print(" r", rev, "p", parents) + refill_hopper(parents) + + rev_to_print = print_test(rev) + if not rev_to_print: + continue + if rev_to_print in seen: + continue + seen.add(rev_to_print) + print_rev(rev_to_print, printer) + +def is_default(rev): + fields = changesets[rev] + branch = fields.get('branch') + if branch: + return False + return rev + + +def is_default_and_not_34(rev): + if not is_default(rev): + return False + fields = changesets[rev] + for rev, branch in get_user_date_to_revs(fields): + if is_34(rev): + return False + return rev + +def is_34(rev): + # if rev == '6343bdbb7085': + # raise StopIteration() + fields = changesets[rev] + branch = fields.get('branch') + if branch != '3.4': + return False + revs = get_user_date_to_revs(fields) + assert (rev, branch) in revs + for rev, branch in revs: + if not branch: + return rev + return False + +class Tool: + unfinished_filename = "/home/larry/.34unfinished" + + def __init__(self): + self.unfinished = None + self._load() + + def _load(self): + if not os.path.isfile(self.unfinished_filename): + return + try: + with open(self.unfinished_filename, "rb") as f: + self.unfinished = pickle.load(f) + except EOFError: + self.unfinished = None + + def _save(self): + with open(self.unfinished_filename, "wb") as f: + pickle.dump(self.unfinished, f) + + def _abandon(self): + self.unfinished = None + try: + os.unlink(self.unfinished_filename) + except OSError: + pass + + def status(self): + """ + Regenerate the status webpage. + """ + f = open("/home/larry/src/python/3.4.merge.status.html", "wt") + + read_changesets() + + def printer(*a): + print(*a, file=f) + + printer(""" + + + +Python 3.4 rc2 merge status + + + + + + + +

+ + +Python 3.4 rc2 merge status +

+""") + + printer("
Notice: this is BETA (don't take it seriously yet)
") + header("Merged", printer) + print_revs(is_34, is_34, printer) + footer(printer) + + header("Unmerged", printer) + print_revs(is_default_and_not_34, is_default, printer) + footer(printer) + + for rev in changesets: + if is_default(rev): + break + + printer(""" +
+

Generated {now}
Current head of default branch is {rev}

+""".format(now=datetime.datetime.now(), rev=rev)) + + printer("") + f.close() + + + def _run_commands(self, commands, u): + commands_run = u['commands run'] + def done(): + self.unfinished = None + self._abandon() + sys.exit(0) + + done_tuple = ("Done!", done) + if done_tuple not in commands: + commands.append(done_tuple) + + while True: + print("Commands:") + commands_set = set('h.d') + for i, (text, cmd) in enumerate(commands): + label = str(i+1) + commands_set.add(label) + label = ' ' + label + ' ' + if text in commands_run: + label = label.replace(' ', '*') + print(" ", label, text) + if isinstance(cmd, str): + cmd = cmd.format_map(u) + else: + cmd = "(python fn " + cmd.__name__ + ")" + print(" ", cmd) + + print(" h Simple help on commands") + s = '' + while s not in commands_set: + s = input("[> ").strip() + if s == '.': + continue + if s == 'd': + pprint.pprint(u) + print() + continue + if s == 'h': + print(""" +Simple help + +. - repeat the command menu +h - print this help message +d - print the internal "unfinished" dict +""") + continue + break + + i = int(s) - 1 + text, cmd = commands[i] + commands_run.add(text) + if isinstance(cmd, str): + cmd = cmd.format_map(u) + result = os.system(cmd) + print() + print("Result:", result) + else: + cmd() + + def pick(self, picked_revision): + """ + Cherry-pick a revision from default to 3.4. + """ + if self.unfinished: + if self.unfinished['default picked revision'] == picked_revision: + return self.finish() + sys.exit("You have unfinished business!\n\nUse the 'finish' command to finish it,\nor the 'abandon' command to abandon it.") + + print("Picking revision", repr(picked_revision)) + read_changesets() + # changesets = collections.OrderedDict() + # user_date_to_revs = {} # "user date" == "{user} {date}", maps to (rev, branch) + # revs = [] + # branches = {} + try: + index = branches[None].index(picked_revision) + except ValueError: + sys.exit("{} is not a revision in Python trunk.".format(picked_revision)) + r_34_head = branches['3.4'][0] + r_34_first_revision = branches['3.4'][-1] + # print("index", index) + # print("3.4 branch", branches['3.4']) + # print("default_from_34", default_from_34) + r_previous = None + # find where it should go in 3.4 + for r in branches['3.4']: + # print("r", r) + if r == r_34_first_revision: + break + r_default = default_from_34[r] + i = branches[None].index(r_default) + if i == index: + sys.exit("{} already in 3.4!".format(picked_revision)) + if i > index: + break + r_previous = r + else: + sys.exit("Unexpected non-termination in pick!") + + if r == r_34_head: + r_rebase_from = None + else: + r_rebase_from = r_previous + + # figure out previous revision in default, in case we need to make a patch + diff_from = branches[None][index + 1] + + fields = changesets[picked_revision] + + self.unfinished = { + 'function': '_pick', + 'threefour rebase from': r_rebase_from, + 'threefour graft here': r, + 'default picked revision': picked_revision, + 'user': fields['user'], + 'date': fields['date'], + 'description': '\n'.join(fields['description']), + 'default diff from': diff_from, + 'threefour picked revision': 'UNKNOWN (detect via "Detect new revision")', + 'commands run': set(), + } + self.finish() + + def _pick(self): + os.chdir("/home/larry/src/python/3.4") + u = self.unfinished + + def detect_new_revision(): + output = subprocess.check_output(['/usr/bin/hg', 'summary']).decode('utf-8').split('\n') + line = output[0] + assert line.startswith('parent:') + line = line[len('parent:'):] + local, colon, r = line.partition(':') + assert colon == ':' + r = r.split()[0].strip() + u['threefour picked revision'] = r + + while True: + patch_path = "/tmp/patch.{default diff from}.to.{default picked revision}.diff".format_map(u) + u['patch path'] = patch_path + + f, commit_message_path = tempfile.mkstemp(suffix='txt') + os.close(f) + with open(commit_message_path, 'wt') as f: + f.write(u['description']) + u['commit message path'] = commit_message_path + + def delete_files(*a): + for path in a: + try: + os.unlink(path) + except OSError: + pass + + atexit.register(delete_files, patch_path, commit_message_path) + + u['EDITOR'] = os.getenv('EDITOR') + + commands = [] + commands.append(("Update to appropriate revision in 3.4 branch", "hg update -r {threefour graft here}")) + commands.append(("Graft revision", "hg graft {default picked revision}")) + + commands.append(("[graft failed step 1] Generate patch", "/usr/bin/hg diff -r {default diff from} -r {default picked revision} > {patch path}")) + commands.append(("[graft failed step 2] Inspect patch", "{EDITOR} {patch path}")) + commands.append(("[graft failed step 3] Apply patch", "/usr/bin/patch -p1 < {patch path}")) + commands.append(("[graft failed step 4] Check in patch", "/usr/bin/hg ci --user '{user}' --date '{date}' --logfile '{commit message path}'")) + + if u.get('threefour rebase from'): + commands.append(("Detect new revision", detect_new_revision)) + c = "hg rebase --source {threefour rebase from} --dest {threefour picked revision}" + commands.append(("Rebase subsequent revisions after grafted revision", c)) + + commands.append(("Update to head of 3.4 branch", "hg update -r 3.4")) + + self._run_commands(commands, u) + + def finish(self): + try: + if not self.unfinished: + sys.exit("No unfinished business!") + function = self.unfinished.get('function') + if not function: + sys.exit("Unfinished state is invalid!") + f = getattr(self, function, None) + if not f: + sys.exit("Unfinished state is invalid!") + f() + except KeyboardInterrupt: + self._save() + + def abandon(self): + if not self.unfinished: + sys.exit("No unfinished business!") + while True: + s = input("Are you sure? (y/n) >") + if s.strip() in 'yn': + break + if s == 'y': + self._abandon() + + + + +t = Tool() + +dp = dryparse.DryParse() +dp.update(t) +dp.main() \ No newline at end of file -- Repository URL: http://hg.python.org/release From python-checkins at python.org Mon Feb 17 22:50:20 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Feb 2014 22:50:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogVW50b2tlbml6ZTog?= =?utf-8?q?An_logically_incorrect_assert_tested_user_input_validity=2E?= Message-ID: <3fSf4r5kcfz7Lk9@mail.python.org> http://hg.python.org/cpython/rev/c896d292080a changeset: 89232:c896d292080a branch: 2.7 parent: 89226:47394ceeaba1 user: Terry Jan Reedy date: Mon Feb 17 16:45:38 2014 -0500 summary: Untokenize: An logically incorrect assert tested user input validity. Replace it with correct logic that raises ValueError for bad input. Issues #8478 and #12691 reported the incorrect logic. Add an Untokenize test case and an initial test method. files: Lib/test/test_tokenize.py | 16 +++++++++++++++- Lib/tokenize.py | 4 +++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -559,9 +559,10 @@ from test import test_support from tokenize import (untokenize, generate_tokens, NUMBER, NAME, OP, - STRING, ENDMARKER, tok_name) + STRING, ENDMARKER, tok_name, Untokenizer) from StringIO import StringIO import os +from unittest import TestCase def dump_tokens(s): """Print out the tokens in s in a table format. @@ -614,12 +615,25 @@ return untokenize(result) +class UntokenizeTest(TestCase): + + def test_bad_input_order(self): + u = Untokenizer() + u.prev_row = 2 + u.prev_col = 2 + with self.assertRaises(ValueError) as cm: + u.add_whitespace((1,3)) + self.assertEqual(cm.exception.args[0], + 'start (1,3) precedes previous end (2,2)') + self.assertRaises(ValueError, u.add_whitespace, (2,1)) + __test__ = {"doctests" : doctests, 'decistmt': decistmt} def test_main(): from test import test_tokenize test_support.run_doctest(test_tokenize, True) + test_support.run_unittest(UntokenizeTest) if __name__ == "__main__": test_main() diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -184,7 +184,9 @@ def add_whitespace(self, start): row, col = start - assert row <= self.prev_row + if row < self.prev_row or row == self.prev_row and col < self.prev_col: + raise ValueError("start ({},{}) precedes previous end ({},{})" + .format(row, col, self.prev_row, self.prev_col)) col_offset = col - self.prev_col if col_offset: self.tokens.append(" " * col_offset) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 17 22:50:22 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Feb 2014 22:50:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogVW50b2tlbml6ZTog?= =?utf-8?q?An_logically_incorrect_assert_tested_user_input_validity=2E?= Message-ID: <3fSf4t0YKrz7LkY@mail.python.org> http://hg.python.org/cpython/rev/51e5a89afb3b changeset: 89233:51e5a89afb3b branch: 3.3 parent: 89227:478523c1aafc user: Terry Jan Reedy date: Mon Feb 17 16:45:48 2014 -0500 summary: Untokenize: An logically incorrect assert tested user input validity. Replace it with correct logic that raises ValueError for bad input. Issues #8478 and #12691 reported the incorrect logic. Add an Untokenize test case and an initial test method. files: Lib/test/test_tokenize.py | 16 +++++++++++++++- Lib/tokenize.py | 4 +++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -638,7 +638,7 @@ from test import support from tokenize import (tokenize, _tokenize, untokenize, NUMBER, NAME, OP, STRING, ENDMARKER, ENCODING, tok_name, detect_encoding, - open as tokenize_open) + open as tokenize_open, Untokenizer) from io import BytesIO from unittest import TestCase import os, sys, glob @@ -1153,6 +1153,19 @@ # See http://bugs.python.org/issue16152 self.assertExactTypeEqual('@ ', token.AT) +class UntokenizeTest(TestCase): + + def test_bad_input_order(self): + u = Untokenizer() + u.prev_row = 2 + u.prev_col = 2 + with self.assertRaises(ValueError) as cm: + u.add_whitespace((1,3)) + self.assertEqual(cm.exception.args[0], + 'start (1,3) precedes previous end (2,2)') + self.assertRaises(ValueError, u.add_whitespace, (2,1)) + + __test__ = {"doctests" : doctests, 'decistmt': decistmt} def test_main(): @@ -1162,6 +1175,7 @@ support.run_unittest(Test_Tokenize) support.run_unittest(TestDetectEncoding) support.run_unittest(TestTokenize) + support.run_unittest(UntokenizeTest) if __name__ == "__main__": test_main() diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -229,7 +229,9 @@ def add_whitespace(self, start): row, col = start - assert row <= self.prev_row + if row < self.prev_row or row == self.prev_row and col < self.prev_col: + raise ValueError("start ({},{}) precedes previous end ({},{})" + .format(row, col, self.prev_row, self.prev_col)) col_offset = col - self.prev_col if col_offset: self.tokens.append(" " * col_offset) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 17 22:50:23 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Feb 2014 22:50:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Untokenize=2C_bad_assert=3A_Merge_with_3=2E3?= Message-ID: <3fSf4v2MWpz7LlS@mail.python.org> http://hg.python.org/cpython/rev/38ac5d82507d changeset: 89234:38ac5d82507d parent: 89231:ea4c74cc4da5 parent: 89233:51e5a89afb3b user: Terry Jan Reedy date: Mon Feb 17 16:46:43 2014 -0500 summary: Untokenize, bad assert: Merge with 3.3 files: Lib/test/test_tokenize.py | 16 +++++++++++++++- Lib/tokenize.py | 4 +++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -638,7 +638,7 @@ from test import support from tokenize import (tokenize, _tokenize, untokenize, NUMBER, NAME, OP, STRING, ENDMARKER, ENCODING, tok_name, detect_encoding, - open as tokenize_open) + open as tokenize_open, Untokenizer) from io import BytesIO from unittest import TestCase import os, sys, glob @@ -1153,6 +1153,19 @@ # See http://bugs.python.org/issue16152 self.assertExactTypeEqual('@ ', token.AT) +class UntokenizeTest(TestCase): + + def test_bad_input_order(self): + u = Untokenizer() + u.prev_row = 2 + u.prev_col = 2 + with self.assertRaises(ValueError) as cm: + u.add_whitespace((1,3)) + self.assertEqual(cm.exception.args[0], + 'start (1,3) precedes previous end (2,2)') + self.assertRaises(ValueError, u.add_whitespace, (2,1)) + + __test__ = {"doctests" : doctests, 'decistmt': decistmt} def test_main(): @@ -1162,6 +1175,7 @@ support.run_unittest(Test_Tokenize) support.run_unittest(TestDetectEncoding) support.run_unittest(TestTokenize) + support.run_unittest(UntokenizeTest) if __name__ == "__main__": test_main() diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -229,7 +229,9 @@ def add_whitespace(self, start): row, col = start - assert row <= self.prev_row + if row < self.prev_row or row == self.prev_row and col < self.prev_col: + raise ValueError("start ({},{}) precedes previous end ({},{})" + .format(row, col, self.prev_row, self.prev_col)) col_offset = col - self.prev_col if col_offset: self.tokens.append(" " * col_offset) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 17 22:50:24 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Feb 2014 22:50:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_whitespace?= Message-ID: <3fSf4w3ny6z7Lkt@mail.python.org> http://hg.python.org/cpython/rev/a539e09be378 changeset: 89235:a539e09be378 branch: 3.3 parent: 89233:51e5a89afb3b user: Terry Jan Reedy date: Mon Feb 17 16:49:06 2014 -0500 summary: whitespace files: Lib/test/test_tokenize.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -1154,14 +1154,14 @@ self.assertExactTypeEqual('@ ', token.AT) class UntokenizeTest(TestCase): - + def test_bad_input_order(self): u = Untokenizer() u.prev_row = 2 u.prev_col = 2 with self.assertRaises(ValueError) as cm: u.add_whitespace((1,3)) - self.assertEqual(cm.exception.args[0], + self.assertEqual(cm.exception.args[0], 'start (1,3) precedes previous end (2,2)') self.assertRaises(ValueError, u.add_whitespace, (2,1)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 17 22:50:25 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 17 Feb 2014 22:50:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3fSf4x5TFfz7LkY@mail.python.org> http://hg.python.org/cpython/rev/164504ecc2e3 changeset: 89236:164504ecc2e3 parent: 89234:38ac5d82507d parent: 89235:a539e09be378 user: Terry Jan Reedy date: Mon Feb 17 16:49:26 2014 -0500 summary: Merge with 3.3 files: Lib/test/test_tokenize.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -1154,14 +1154,14 @@ self.assertExactTypeEqual('@ ', token.AT) class UntokenizeTest(TestCase): - + def test_bad_input_order(self): u = Untokenizer() u.prev_row = 2 u.prev_col = 2 with self.assertRaises(ValueError) as cm: u.add_whitespace((1,3)) - self.assertEqual(cm.exception.args[0], + self.assertEqual(cm.exception.args[0], 'start (1,3) precedes previous end (2,2)') self.assertRaises(ValueError, u.add_whitespace, (2,1)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 00:12:06 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 00:12:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320655=3A_Fix_test?= =?utf-8?q?=5Fasyncio=2C_run_also_subprocess_tests=2E_Patch_written_by?= Message-ID: <3fSgvB1jTsz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/b3987d758e49 changeset: 89237:b3987d758e49 user: Victor Stinner date: Tue Feb 18 00:11:21 2014 +0100 summary: Issue #20655: Fix test_asyncio, run also subprocess tests. Patch written by Vajrasky Kok. files: Lib/test/test_asyncio/tests.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_asyncio/tests.txt b/Lib/test/test_asyncio/tests.txt --- a/Lib/test/test_asyncio/tests.txt +++ b/Lib/test/test_asyncio/tests.txt @@ -6,6 +6,7 @@ test_asyncio.test_queues test_asyncio.test_selector_events test_asyncio.test_streams +test_asyncio.test_subprocess test_asyncio.test_tasks test_asyncio.test_transports test_asyncio.test_unix_events -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 01:31:11 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 01:31:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320667=3A_test=5Fa?= =?utf-8?q?syncio=3A_Skip_KqueueEventLoopTests=2Etest=5Fread=5Fpty=5Foutpu?= =?utf-8?b?dCgpIG9u?= Message-ID: <3fSjfR68F7z7Llw@mail.python.org> http://hg.python.org/cpython/rev/d548829765cd changeset: 89238:d548829765cd user: Victor Stinner date: Tue Feb 18 01:30:03 2014 +0100 summary: Issue #20667: test_asyncio: Skip KqueueEventLoopTests.test_read_pty_output() on OpenBSD older than 5.5 files: Lib/test/support/__init__.py | 10 ++++++++++ Lib/test/test_asyncio/test_events.py | 3 +++ 2 files changed, 13 insertions(+), 0 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -78,6 +78,7 @@ "create_empty_file", "can_symlink", "fs_is_case_insensitive", # unittest "is_resource_enabled", "requires", "requires_freebsd_version", + "requires_openbsd_version", "requires_linux_version", "requires_mac_ver", "check_syntax_error", "TransientResource", "time_out", "socket_peer_reset", "ioerror_peer_reset", "transient_internet", "BasicTestRunner", "run_unittest", "run_doctest", @@ -467,6 +468,15 @@ """ return _requires_unix_version('FreeBSD', min_version) +def requires_openbsd_version(*min_version): + """Decorator raising SkipTest if the OS is OpenBSD and the OpenBSD version + is less than `min_version`. + + For example, @requires_freebsd_version(5, 4) raises SkipTest if the FreeBSD + version is less than 5.4. + """ + return _requires_unix_version('OpenBSD', min_version) + def requires_linux_version(*min_version): """Decorator raising SkipTest if the OS is Linux and the Linux version is less than `min_version`. diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1622,6 +1622,9 @@ # kqueue doesn't support character devices (PTY) on Mac OS X older # than 10.9 (Maverick) @support.requires_mac_ver(10, 9) + # Issue #20667: KqueueEventLoopTests.test_read_pty_output() + # hangs on OpenBSD 5.4 + @support.requires_openbsd_version(5, 5) def test_read_pty_output(self): super().test_read_pty_output() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 01:36:29 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 01:36:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320656=3A_Fix_sele?= =?utf-8?q?ct=2Eselect=28=29_on_OpenBSD_64-bit?= Message-ID: <3fSjmY758Hz7LjS@mail.python.org> http://hg.python.org/cpython/rev/79ccf36b0fd0 changeset: 89239:79ccf36b0fd0 user: Victor Stinner date: Tue Feb 18 01:35:40 2014 +0100 summary: Close #20656: Fix select.select() on OpenBSD 64-bit files: Modules/selectmodule.c | 22 ++++++++++++---------- 1 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -212,11 +212,18 @@ return NULL; } else { -#ifdef MS_WINDOWS + /* On OpenBSD 5.4, timeval.tv_sec is a long. + * Example: long is 64-bit, whereas time_t is 32-bit. */ time_t sec; - if (_PyTime_ObjectToTimeval(tout, &sec, &tv.tv_usec, + /* On OS X 64-bit, timeval.tv_usec is an int (and thus still 4 + bytes as required), but no longer defined by a long. */ + long usec; + if (_PyTime_ObjectToTimeval(tout, &sec, &usec, _PyTime_ROUND_UP) == -1) return NULL; +#ifdef MS_WINDOWS + /* On Windows, timeval.tv_sec is a long (32 bit), + * whereas time_t can be 64-bit. */ assert(sizeof(tv.tv_sec) == sizeof(long)); #if SIZEOF_TIME_T > SIZEOF_LONG if (sec > LONG_MAX) { @@ -225,16 +232,11 @@ return NULL; } #endif - tv.tv_sec = (long)sec; #else - /* 64-bit OS X has struct timeval.tv_usec as an int (and thus still 4 - bytes as required), but no longer defined by a long. */ - long tv_usec; - if (_PyTime_ObjectToTimeval(tout, &tv.tv_sec, &tv_usec, - _PyTime_ROUND_UP) == -1) - return NULL; - tv.tv_usec = tv_usec; + assert(sizeof(tv.tv_sec) >= sizeof(sec)); #endif + tv.tv_sec = sec; + tv.tv_usec = usec; if (tv.tv_sec < 0) { PyErr_SetString(PyExc_ValueError, "timeout must be non-negative"); return NULL; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 05:17:23 2014 From: python-checkins at python.org (terry.reedy) Date: Tue, 18 Feb 2014 05:17:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzg0Nzg6?= =?utf-8?q?_Untokenizer=2Ecompat_now_processes_first_token_from_iterator_i?= =?utf-8?q?nput=2E?= Message-ID: <3fSpgR2p28z7Ll5@mail.python.org> http://hg.python.org/cpython/rev/c2517a37c13a changeset: 89240:c2517a37c13a branch: 2.7 parent: 89232:c896d292080a user: Terry Jan Reedy date: Mon Feb 17 23:12:07 2014 -0500 summary: Issue #8478: Untokenizer.compat now processes first token from iterator input. Patch based on lines from Georg Brandl, Eric Snow, and Gareth Rees. files: Lib/test/test_tokenize.py | 10 +++++++++- Lib/tokenize.py | 16 +++++++--------- Misc/NEWS | 3 +++ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -627,9 +627,17 @@ 'start (1,3) precedes previous end (2,2)') self.assertRaises(ValueError, u.add_whitespace, (2,1)) + def test_iter_compat(self): + u = Untokenizer() + token = (NAME, 'Hello') + u.compat(token, iter([])) + self.assertEqual(u.tokens, ["Hello "]) + u = Untokenizer() + self.assertEqual(u.untokenize(iter([token])), 'Hello ') + + __test__ = {"doctests" : doctests, 'decistmt': decistmt} - def test_main(): from test import test_tokenize test_support.run_doctest(test_tokenize, True) diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -26,6 +26,7 @@ __credits__ = ('GvR, ESR, Tim Peters, Thomas Wouters, Fred Drake, ' 'Skip Montanaro, Raymond Hettinger') +from itertools import chain import string, re from token import * @@ -192,9 +193,10 @@ self.tokens.append(" " * col_offset) def untokenize(self, iterable): - for t in iterable: + it = iter(iterable) + for t in it: if len(t) == 2: - self.compat(t, iterable) + self.compat(t, it) break tok_type, token, start, end, line = t self.add_whitespace(start) @@ -206,16 +208,12 @@ return "".join(self.tokens) def compat(self, token, iterable): - startline = False indents = [] toks_append = self.tokens.append - toknum, tokval = token - if toknum in (NAME, NUMBER): - tokval += ' ' - if toknum in (NEWLINE, NL): - startline = True + startline = token[0] in (NEWLINE, NL) prevstring = False - for tok in iterable: + + for tok in chain([token], iterable): toknum, tokval = tok[:2] if toknum in (NAME, NUMBER): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,9 @@ - Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. Based on patch by Stephen Tu. +- Issue #8478: Untokenizer.compat processes first token from iterator input. + Patch based on lines from Georg Brandl, Eric Snow, and Gareth Rees. + - Issue #20594: Avoid name clash with the libc function posix_close. - Issue #19856: shutil.move() failed to move a directory to other directory -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 05:17:24 2014 From: python-checkins at python.org (terry.reedy) Date: Tue, 18 Feb 2014 05:17:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzg0Nzg6?= =?utf-8?q?_Untokenizer=2Ecompat_now_processes_first_token_from_iterator_i?= =?utf-8?q?nput=2E?= Message-ID: <3fSpgS4QdTz7LlM@mail.python.org> http://hg.python.org/cpython/rev/b6d6ca792b64 changeset: 89241:b6d6ca792b64 branch: 3.3 parent: 89235:a539e09be378 user: Terry Jan Reedy date: Mon Feb 17 23:12:16 2014 -0500 summary: Issue #8478: Untokenizer.compat now processes first token from iterator input. Patch based on lines from Georg Brandl, Eric Snow, and Gareth Rees. files: Lib/test/test_tokenize.py | 13 +++++++++++++ Lib/tokenize.py | 24 +++++++++++------------- Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -1165,6 +1165,19 @@ 'start (1,3) precedes previous end (2,2)') self.assertRaises(ValueError, u.add_whitespace, (2,1)) + def test_iter_compat(self): + u = Untokenizer() + token = (NAME, 'Hello') + tokens = [(ENCODING, 'utf-8'), token] + u.compat(token, iter([])) + self.assertEqual(u.tokens, ["Hello "]) + u = Untokenizer() + self.assertEqual(u.untokenize(iter([token])), 'Hello ') + u = Untokenizer() + self.assertEqual(u.untokenize(iter(tokens)), 'Hello ') + self.assertEqual(u.encoding, 'utf-8') + self.assertEqual(untokenize(iter(tokens)), b'Hello ') + __test__ = {"doctests" : doctests, 'decistmt': decistmt} diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -25,12 +25,14 @@ 'Skip Montanaro, Raymond Hettinger, Trent Nelson, ' 'Michael Foord') import builtins +from codecs import lookup, BOM_UTF8 +import collections +from io import TextIOWrapper +from itertools import chain import re import sys from token import * -from codecs import lookup, BOM_UTF8 -import collections -from io import TextIOWrapper + cookie_re = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)', re.ASCII) blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII) @@ -237,9 +239,10 @@ self.tokens.append(" " * col_offset) def untokenize(self, iterable): - for t in iterable: + it = iter(iterable) + for t in it: if len(t) == 2: - self.compat(t, iterable) + self.compat(t, it) break tok_type, token, start, end, line = t if tok_type == ENCODING: @@ -254,17 +257,12 @@ return "".join(self.tokens) def compat(self, token, iterable): - startline = False indents = [] toks_append = self.tokens.append - toknum, tokval = token + startline = token[0] in (NEWLINE, NL) + prevstring = False - if toknum in (NAME, NUMBER): - tokval += ' ' - if toknum in (NEWLINE, NL): - startline = True - prevstring = False - for tok in iterable: + for tok in chain([token], iterable): toknum, tokval = tok[:2] if toknum == ENCODING: self.encoding = tokval diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -26,6 +26,9 @@ - Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. Based on patch by Stephen Tu. +- Issue #8478: Untokenizer.compat processes first token from iterator input. + Patch based on lines from Georg Brandl, Eric Snow, and Gareth Rees. + - Issue #20594: Avoid name clash with the libc function posix_close. - Issue #19856: shutil.move() failed to move a directory to other directory -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 05:17:25 2014 From: python-checkins at python.org (terry.reedy) Date: Tue, 18 Feb 2014 05:17:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3fSpgT62hbz7LlN@mail.python.org> http://hg.python.org/cpython/rev/1a1661750890 changeset: 89242:1a1661750890 parent: 89239:79ccf36b0fd0 parent: 89241:b6d6ca792b64 user: Terry Jan Reedy date: Mon Feb 17 23:12:37 2014 -0500 summary: Merge with 3.3 files: Lib/test/test_tokenize.py | 13 +++++++++++++ Lib/tokenize.py | 24 +++++++++++------------- Misc/NEWS | 3 +++ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -1165,6 +1165,19 @@ 'start (1,3) precedes previous end (2,2)') self.assertRaises(ValueError, u.add_whitespace, (2,1)) + def test_iter_compat(self): + u = Untokenizer() + token = (NAME, 'Hello') + tokens = [(ENCODING, 'utf-8'), token] + u.compat(token, iter([])) + self.assertEqual(u.tokens, ["Hello "]) + u = Untokenizer() + self.assertEqual(u.untokenize(iter([token])), 'Hello ') + u = Untokenizer() + self.assertEqual(u.untokenize(iter(tokens)), 'Hello ') + self.assertEqual(u.encoding, 'utf-8') + self.assertEqual(untokenize(iter(tokens)), b'Hello ') + __test__ = {"doctests" : doctests, 'decistmt': decistmt} diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -25,12 +25,14 @@ 'Skip Montanaro, Raymond Hettinger, Trent Nelson, ' 'Michael Foord') import builtins +from codecs import lookup, BOM_UTF8 +import collections +from io import TextIOWrapper +from itertools import chain import re import sys from token import * -from codecs import lookup, BOM_UTF8 -import collections -from io import TextIOWrapper + cookie_re = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)', re.ASCII) blank_re = re.compile(br'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII) @@ -237,9 +239,10 @@ self.tokens.append(" " * col_offset) def untokenize(self, iterable): - for t in iterable: + it = iter(iterable) + for t in it: if len(t) == 2: - self.compat(t, iterable) + self.compat(t, it) break tok_type, token, start, end, line = t if tok_type == ENCODING: @@ -254,17 +257,12 @@ return "".join(self.tokens) def compat(self, token, iterable): - startline = False indents = [] toks_append = self.tokens.append - toknum, tokval = token + startline = token[0] in (NEWLINE, NL) + prevstring = False - if toknum in (NAME, NUMBER): - tokval += ' ' - if toknum in (NEWLINE, NL): - startline = True - prevstring = False - for tok in iterable: + for tok in chain([token], iterable): toknum, tokval = tok[:2] if toknum == ENCODING: self.encoding = tokval diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,9 @@ - Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. Based on patch by Stephen Tu. +- Issue #8478: Untokenizer.compat processes first token from iterator input. + Patch based on lines from Georg Brandl, Eric Snow, and Gareth Rees. + - Issue #20594: Avoid name clash with the libc function posix_close. - Issue #19856: shutil.move() failed to move a directory to other directory -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 05:17:27 2014 From: python-checkins at python.org (terry.reedy) Date: Tue, 18 Feb 2014 05:17:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_whitespace?= Message-ID: <3fSpgW0LlKz7LmB@mail.python.org> http://hg.python.org/cpython/rev/465d81c1b2fc changeset: 89243:465d81c1b2fc branch: 2.7 parent: 89240:c2517a37c13a user: Terry Jan Reedy date: Mon Feb 17 23:16:26 2014 -0500 summary: whitespace files: Lib/tokenize.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -212,7 +212,7 @@ toks_append = self.tokens.append startline = token[0] in (NEWLINE, NL) prevstring = False - + for tok in chain([token], iterable): toknum, tokval = tok[:2] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 08:35:42 2014 From: python-checkins at python.org (georg.brandl) Date: Tue, 18 Feb 2014 08:35:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_PEP_463_by_Chris_Angelico?= =?utf-8?q?=2E?= Message-ID: <3fSv4G5lBMzSTC@mail.python.org> http://hg.python.org/peps/rev/ec4012d1e5e6 changeset: 5375:ec4012d1e5e6 user: Georg Brandl date: Tue Feb 18 08:36:30 2014 +0100 summary: Add PEP 463 by Chris Angelico. files: pep-0463.txt | 436 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 436 insertions(+), 0 deletions(-) diff --git a/pep-0463.txt b/pep-0463.txt new file mode 100644 --- /dev/null +++ b/pep-0463.txt @@ -0,0 +1,436 @@ +PEP: 463 +Title: Exception-catching expressions +Version: $Revision$ +Last-Modified: $Date$ +Author: Chris Angelico +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 15-Feb-2014 +Python-Version: 3.5 +Post-History: 16-Feb-2014 + + +Abstract +======== + +Just as PEP 308 introduced a means of value-based conditions in an +expression, this system allows exception-based conditions to be used +as part of an expression. + + +Motivation +========== + +A number of functions and methods have parameters which will cause +them to return a specified value instead of raising an exception. The +current system is ad-hoc and inconsistent, and requires that each +function be individually written to have this functionality; not all +support this. + +* dict.get(key, default) - second positional argument in place of + KeyError + +* next(iter, default) - second positional argument in place of + StopIteration + +* list.pop() - no way to return a default + +* seq[index] - no way to handle a bounds error + +* min(sequence, default=default) - keyword argument in place of + ValueError + +* sum(sequence, start=default) - slightly different but can do the + same job + +* statistics.mean(data) - no way to handle an empty iterator + +Additionally, this syntax would allow a convenient way to capture +exceptions in interactive Python; returned values are captured by "_", +but exceptions currently are not. This could be spelled: + +>>> expr except Exception as e: e + + +Rationale +========= + +The current system requires that a function author predict the need +for a default, and implement support for it. If this is not done, a +full try/except block is needed. + +Since try/except is a statement, it is impossible to catch exceptions +in the middle of an expression. Just as if/else does for conditionals +and lambda does for function definitions, so does this allow exception +catching in an expression context. + +This provides a clean and consistent way for a function to provide a +default: it simply raises an appropriate exception, and the caller +catches it. + +There's no convenient way to write a helper function to do this; the +nearest is something ugly using either lambda:: + + def except_(expression, exception_list, default): + try: + return expression() + except exception_list as e: + return default(e) + value = except_(lambda: 1/x, ZeroDivisionError, lambda e: float("nan")) + +which is clunky, and unable to handle multiple exception clauses; or +eval:: + + def except_(expression, exception_list, default): + try: + return eval(expression, globals_of_caller(), locals_of_caller()) + except exception_list as exc: + l = locals_of_caller().copy() + l['exc'] = exc + return eval(default, globals_of_caller(), l) + + def globals_of_caller(): + return sys._getframe(2).f_globals + + def locals_of_caller(): + return sys._getframe(2).f_locals + + value = except_("""1/x""",ZeroDivisionError,""" "Can't divide by zero" """) + +which is even clunkier, and relies on implementation-dependent hacks. +(Writing globals_of_caller() and locals_of_caller() for interpreters +other than CPython is left as an exercise for the reader.) + +Raymond Hettinger `expresses`__ a desire for such a consistent +API. Something similar has been `requested`__ `multiple`__ `times`__ +in the past. + +__ https://mail.python.org/pipermail/python-ideas/2014-February/025443.html +__ https://mail.python.org/pipermail/python-ideas/2013-March/019760.html +__ https://mail.python.org/pipermail/python-ideas/2009-August/005441.html +__ https://mail.python.org/pipermail/python-ideas/2008-August/001801.html + + +Proposal +======== + +Just as the 'or' operator and the three part 'if-else' expression give +short circuiting methods of catching a falsy value and replacing it, +this syntax gives a short-circuiting method of catching an exception +and replacing it. + +This currently works:: + + lst = [1, 2, None, 3] + value = lst[2] or "No value" + +The proposal adds this:: + + lst = [1, 2] + value = lst[2] except IndexError: "No value" + +Specifically, the syntax proposed is:: + + expr except exc [as e]: default [except exc2 [as e]: default2] ... + +where expr, exc, and default are all expressions. First, expr is +evaluated. If no exception is raised, its value is the value of the +overall expression. If any exception is raised, exc is evaluated, and +should result in either a type or a tuple, just as with the statement +form of try/except. Any matching exception will result in the +corresponding default expression being evaluated and becoming the +value of the expression. As with the statement form of try/ except, +subsequent except clauses will be checked if the first one does not +match, and if none match, the raised exception will propagate upward. +Also as with the try/except statement, the keyword 'as' can be used to +bind the exception object to a local name. + +Omitting the exception list should be legal, just as with the +statement form of try/except, though this should of course be +discouraged by PEP 8. + +The exception object can be captured just as in a normal try/except +block:: + + # Return the next yielded or returned value from a generator + value = next(it) except StopIteration as e: e.args[0] + +This is effectively equivalent to:: + + try: + _ = next(it) + except StopIteration as e: + _ = e.args[0] + value = _ + +This ternary operator would be between lambda and if/else in +precedence. + + +Chaining +-------- + +Multiple 'except' keywords can be used, and they will all catch +exceptions raised in the original expression (only):: + + # Will catch any of the listed exceptions thrown by expr; + # any exception thrown by a default expression will propagate. + value = (expr + except Exception1 [as e]: default1 + except Exception2 [as e]: default2 + # ... except ExceptionN [as e]: defaultN + ) + +Using parentheses to force an alternative interpretation works as +expected:: + + # Will catch an Exception2 thrown by either expr or default1 + value = ( + (expr except Exception1: default1) + except Exception2: default2 + ) + # Will catch an Exception2 thrown by default1 only + value = (expr except Exception1: + (default1 except Exception2: default2) + ) + +This last form is confusing and should be discouraged by PEP 8, but it +is syntactically legal: you can put any sort of expression inside a +ternary-except; ternary-except is an expression; therefore you can put +a ternary-except inside a ternary-except. + + +Alternative Proposals +===================== + +Discussion on python-ideas brought up the following syntax suggestions:: + + value = expr except default if Exception [as e] + value = expr except default for Exception [as e] + value = expr except default from Exception [as e] + value = expr except Exception [as e] return default + value = expr except (Exception [as e]: default) + value = expr except Exception [as e] try default + value = expr except Exception [as e] continue with default + value = default except Exception [as e] else expr + value = try expr except Exception [as e]: default + value = expr except Exception [as e] pass default + +It has also been suggested that a new keyword be created, rather than +reusing an existing one. Such proposals fall into the same structure +as the last form, but with a different keyword in place of 'pass'. +Suggestions include 'then', 'when', and 'use'. + +Additionally, the following has been suggested as a similar +short-hand, though not technically an expression:: + + statement except Exception: pass + + try: + statement + except Exception: + pass + + +Open Issues +=========== + +Commas between multiple except clauses +-------------------------------------- + +Where there are multiple except clauses, should they be separated by +commas? It may be easier for the parser, that way:: + + value = (expr + except Exception1 [as e]: default1, + except Exception2 [as e]: default2, + # ... except ExceptionN [as e]: defaultN, + ) + +with an optional comma after the last, as per tuple rules. Downside: +Omitting the comma would be syntactically valid, and would have almost +identical semantics, but would nest the entire preceding expression in +its exception catching rig - a matching exception raised in the +default clause would be caught by the subsequent except clause. As +this difference is so subtle, it runs the risk of being a major bug +magnet. + +As a mitigation of this risk, this form:: + + value = expr except Exception1: default1 except Exception2: default2 + +could be syntactically forbidden, and parentheses required if the +programmer actually wants that behaviour:: + + value = (expr except Exception1: default1) except Exception2: default2 + +This would prevent the accidental omission of a comma from changing +the expression's meaning. + + +Parentheses around the entire expression +---------------------------------------- + +Generator expressions require parentheses, unless they would be +strictly redundant. Ambiguities with except expressions could be +resolved in the same way, forcing nested except-in-except trees to be +correctly parenthesized and requiring that the outer expression be +clearly delineated. `Steven D'Aprano elaborates on the issue.`__ + +__ https://mail.python.org/pipermail/python-ideas/2014-February/025647.html + + +Parentheses around the except clauses +------------------------------------- + +Should it be legal to parenthesize the except clauses, separately from +the expression that could raise? Example:: + + value = expr ( + except Exception1 [as e]: default1 + except Exception2 [as e]: default2 + # ... except ExceptionN [as e]: defaultN + ) + + +Scope of default expressions and 'as' +------------------------------------- + +In a try/except block, the use of 'as' to capture the exception object +creates a local name binding, and implicitly deletes that binding in a +finally clause. As 'finally' is not a part of this proposal (see +below), this makes it tricky to describe; also, this use of 'as' gives +a way to create a name binding in an expression context. Should the +default clause have an inner scope in which the name exists, shadowing +anything of the same name elsewhere? Should it behave the same way the +statement try/except does, and unbind the name? Should it bind the +name and leave it bound? (Almost certainly not; this behaviour was +changed in Python 3 for good reason.) + +(The inner scope idea is tempting, but currently CPython handles list +comprehensions with a nested function call, as this is considered +easier. It may be of value to simplify both comprehensions and except +expressions, but that is a completely separate proposal to this PEP; +alternatively, it may be better to stick with what's known to +work. `Nick Coghlan elaborates.`__) + +__ https://mail.python.org/pipermail/python-ideas/2014-February/025702.html + + +Example usage +============= + +For each example, an approximately-equivalent statement form is given, +to show how the expression will be parsed. These are not always +strictly equivalent, but will accomplish the same purpose. It is NOT +safe for the interpreter to translate one into the other. + +Perform some lengthy calculations in EAFP mode, handling division by +zero as a sort of sticky NaN:: + + value = calculate(x) except ZeroDivisionError: float("nan") + + try: + value = calculate(x) + except ZeroDivisionError: + value = float("nan") + +Retrieving from a generator, either the next yielded value or the +returned, and coping with the absence of such a return value:: + + value = (next(it) + except StopIteration as e: + (e.args[0] except IndexError: None) + ) + + try: + value = next(it) + except StopIteration as e: + try: + value = e.args[0] + except IndexError: + value = None + +Calculate the mean of a series of numbers, falling back on zero:: + + value = statistics.mean(lst) except statistics.StatisticsError: 0 + + try: + value = statistics.mean(lst) + except statistics.StatisticsError: + value = 0 + +Set a PyGTK label to a human-readable result from fetching a URL:: + + display.set_text( + urllib.request.urlopen(url) + except urllib.error.HTTPError as e: "Error %d: %s"%(x.getcode(), x.msg) + except (ValueError, urllib.error.URLError) as e: "Invalid URL: "+str(e) + ) + + try: + display.set_text(urllib.request.urlopen(url)) + except urllib.error.HTTPError as e: + display.set_text("Error %d: %s"%(x.getcode(), x.msg)) + except (ValueError, urllib.error.URLError) as e: + display.set_text("Invalid URL: "+str(e)) + +Retrieving a message from either a cache or the internet,with auth +check:: + + logging.info("Message shown to user: %s",((cache[k] + except LookupError: + (backend.read(k) except OSError: 'Resource not available') + ) + if check_permission(k) else 'Access denied' + ) except: "I'm an idiot and using a bare except clause") + + try: + if check_permission(k): + try: + _ = cache[k] + except LookupError: + try: + _ = backend.read(k) + except OSError: + _ = 'Resource not available' + else: + _ = 'Access denied' + except: + _ = "I'm an idiot and using a bare except clause" + logging.info("Message shown to user: %s", _) + +Looking up objects in a sparse list of overrides:: + + (overrides[x] or default except IndexError: default).ping() + + try: + (overrides[x] or default).ping() + except IndexError: + default.ping() + + +Rejected sub-proposals +====================== + +The statement form try... finally or try... except... finally has no +logical corresponding expression form. Therefore the finally keyword +is not a part of this proposal, in any way. + + +Copyright +========= + +This document has been placed in the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Feb 18 09:20:30 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 09:20:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320667=3A_KqueueEv?= =?utf-8?q?entLoopTests=2Etest=5Fread=5Fpty=5Foutput=28=29_hangs_also_on_O?= =?utf-8?q?penBSD?= Message-ID: <3fSw3y3cZ3z7Ljh@mail.python.org> http://hg.python.org/cpython/rev/b2498889ad8d changeset: 89244:b2498889ad8d parent: 89242:1a1661750890 user: Victor Stinner date: Tue Feb 18 09:13:47 2014 +0100 summary: Issue #20667: KqueueEventLoopTests.test_read_pty_output() hangs also on OpenBSD 5.5. files: Lib/test/support/__init__.py | 10 ---------- Lib/test/test_asyncio/test_events.py | 5 +++-- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -78,7 +78,6 @@ "create_empty_file", "can_symlink", "fs_is_case_insensitive", # unittest "is_resource_enabled", "requires", "requires_freebsd_version", - "requires_openbsd_version", "requires_linux_version", "requires_mac_ver", "check_syntax_error", "TransientResource", "time_out", "socket_peer_reset", "ioerror_peer_reset", "transient_internet", "BasicTestRunner", "run_unittest", "run_doctest", @@ -468,15 +467,6 @@ """ return _requires_unix_version('FreeBSD', min_version) -def requires_openbsd_version(*min_version): - """Decorator raising SkipTest if the OS is OpenBSD and the OpenBSD version - is less than `min_version`. - - For example, @requires_freebsd_version(5, 4) raises SkipTest if the FreeBSD - version is less than 5.4. - """ - return _requires_unix_version('OpenBSD', min_version) - def requires_linux_version(*min_version): """Decorator raising SkipTest if the OS is Linux and the Linux version is less than `min_version`. diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1623,8 +1623,9 @@ # than 10.9 (Maverick) @support.requires_mac_ver(10, 9) # Issue #20667: KqueueEventLoopTests.test_read_pty_output() - # hangs on OpenBSD 5.4 - @support.requires_openbsd_version(5, 5) + # hangs on OpenBSD 5.5 + @unittest.skipIf(sys.platform.startswith('openbsd'), + 'test hangs on OpenBSD') def test_read_pty_output(self): super().test_read_pty_output() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 09:20:31 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 09:20:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320564=3A_Skip_tes?= =?utf-8?q?ts_on_lock+signals_on_OpenBSD?= Message-ID: <3fSw3z60tGz7LmZ@mail.python.org> http://hg.python.org/cpython/rev/a3d54bb04cbb changeset: 89245:a3d54bb04cbb user: Victor Stinner date: Tue Feb 18 09:19:48 2014 +0100 summary: Issue #20564: Skip tests on lock+signals on OpenBSD files: Lib/test/test_threadsignals.py | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_threadsignals.py b/Lib/test/test_threadsignals.py --- a/Lib/test/test_threadsignals.py +++ b/Lib/test/test_threadsignals.py @@ -74,6 +74,9 @@ @unittest.skipIf(USING_PTHREAD_COND, 'POSIX condition variables cannot be interrupted') + # Issue #20564: sem_timedwait() cannot be interrupted on OpenBSD + @unittest.skipIf(sys.platform.startswith('openbsd'), + 'lock cannot be interrupted on OpenBSD') def test_lock_acquire_interruption(self): # Mimic receiving a SIGINT (KeyboardInterrupt) with SIGALRM while stuck # in a deadlock. @@ -97,6 +100,9 @@ @unittest.skipIf(USING_PTHREAD_COND, 'POSIX condition variables cannot be interrupted') + # Issue #20564: sem_timedwait() cannot be interrupted on OpenBSD + @unittest.skipIf(sys.platform.startswith('openbsd'), + 'lock cannot be interrupted on OpenBSD') def test_rlock_acquire_interruption(self): # Mimic receiving a SIGINT (KeyboardInterrupt) with SIGALRM while stuck # in a deadlock. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 09:22:12 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 09:22:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320649=3A_Fix_typo?= =?utf-8?q?_in_asyncio_doc=2E_Patch_written_by_Brett_Cannon=2E?= Message-ID: <3fSw5w6KJJzSJf@mail.python.org> http://hg.python.org/cpython/rev/6b09a2cf1744 changeset: 89246:6b09a2cf1744 user: Victor Stinner date: Tue Feb 18 09:22:00 2014 +0100 summary: Close #20649: Fix typo in asyncio doc. Patch written by Brett Cannon. files: Doc/library/asyncio-dev.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -13,7 +13,7 @@ ------------------------------ An event loop runs in a thread and executes all callbacks and tasks in the same -thread. While a task in running in the event loop, no other task is running in +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 and the event loop executes the next task. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 09:30:45 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 09:30:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320656=3A_Restore_?= =?utf-8?q?explicit_downcast_in_select=5Fselect=28=29=2E?= Message-ID: <3fSwHn3YfDz7LjZ@mail.python.org> http://hg.python.org/cpython/rev/6c186975ee43 changeset: 89247:6c186975ee43 user: Victor Stinner date: Tue Feb 18 09:30:33 2014 +0100 summary: Issue #20656: Restore explicit downcast in select_select(). Cast from time_t (64 bit) to long (32 bit). It should fix a compiler warning. files: Modules/selectmodule.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -232,10 +232,11 @@ return NULL; } #endif + tv.tv_sec = (long)sec; #else assert(sizeof(tv.tv_sec) >= sizeof(sec)); + tv.tv_sec = sec; #endif - tv.tv_sec = sec; tv.tv_usec = usec; if (tv.tv_sec < 0) { PyErr_SetString(PyExc_ValueError, "timeout must be non-negative"); -- Repository URL: http://hg.python.org/cpython From victor.stinner at gmail.com Tue Feb 18 09:32:07 2014 From: victor.stinner at gmail.com (Victor Stinner) Date: Tue, 18 Feb 2014 09:32:07 +0100 Subject: [Python-checkins] [Python-Dev] cpython: Close #20656: Fix select.select() on OpenBSD 64-bit In-Reply-To: References: <3fSjmY758Hz7LjS@mail.python.org> Message-ID: Hi, 2014-02-18 6:19 GMT+01:00 Zachary Ware : > On Mon, Feb 17, 2014 at 6:36 PM, victor.stinner > wrote: >> http://hg.python.org/cpython/rev/79ccf36b0fd0 >> changeset: 89239:79ccf36b0fd0 >> user: Victor Stinner >> date: Tue Feb 18 01:35:40 2014 +0100 >> summary: >> Close #20656: Fix select.select() on OpenBSD 64-bit >> >> files: >> Modules/selectmodule.c | 22 ++++++++++++---------- >> 1 files changed, 12 insertions(+), 10 deletions(-) > > This changeset caused a compile warning on 32-bit Windows: > > ..\Modules\selectmodule.c(238): warning C4244: '=' : conversion from > 'time_t' to 'long', possible loss of data > [P:\ath\to\cpython\PCbuild\select.vcxproj] Ah yes, I didn't remember why I wrote the downcast initially. You're right, it is still neeed (on 64-bit Windows). I restored it: --- user: Victor Stinner date: Tue Feb 18 09:30:33 2014 +0100 files: Modules/selectmodule.c description: Issue #20656: Restore explicit downcast in select_select(). Cast from time_t (64 bit) to long (32 bit). It should fix a compiler warning. --- Victor From solipsis at pitrou.net Tue Feb 18 09:35:50 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 18 Feb 2014 09:35:50 +0100 Subject: [Python-checkins] Daily reference leaks (79ccf36b0fd0): sum=0 Message-ID: results for 79ccf36b0fd0 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 4] memory blocks, sum=4 test_site leaked [-2, 0, 0] references, sum=-2 test_site leaked [-2, 0, 0] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog7hKB5s', '-x'] From python-checkins at python.org Tue Feb 18 09:37:54 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 09:37:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320493=3A_Document?= =?utf-8?q?_that_asyncio_should_not_exceed_one_day?= Message-ID: <3fSwS24FGdz7LjZ@mail.python.org> http://hg.python.org/cpython/rev/79e5bb0d9b8e changeset: 89248:79e5bb0d9b8e user: Victor Stinner date: Tue Feb 18 09:37:43 2014 +0100 summary: Issue #20493: Document that asyncio should not exceed one day files: Doc/library/asyncio-eventloop.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -157,6 +157,10 @@ implementation; ideally it is a monotonic clock. This will generally be a different clock than :func:`time.time`. +.. note:: + + Timeouts (relative *delay* or absolute *when*) should not exceed one day. + .. method:: BaseEventLoop.call_later(delay, callback, *args) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 15:42:08 2014 From: python-checkins at python.org (zach.ware) Date: Tue, 18 Feb 2014 15:42:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTEw?= =?utf-8?q?=3A_Rewrote_test=5Fexit_in_test=5Fsys_to_match_existing_comment?= =?utf-8?q?s?= Message-ID: <3fT4XJ3Hh9z7Lkv@mail.python.org> http://hg.python.org/cpython/rev/63f0a1e95d2b changeset: 89249:63f0a1e95d2b branch: 2.7 parent: 89243:465d81c1b2fc user: Zachary Ware date: Tue Feb 18 08:36:14 2014 -0600 summary: Issue #20510: Rewrote test_exit in test_sys to match existing comments and to modernize. Initial patch by Gareth Rees. files: Lib/test/test_sys.py | 86 +++++++++++-------------------- Misc/NEWS | 4 + 2 files changed, 35 insertions(+), 55 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1,5 +1,6 @@ # -*- coding: iso-8859-1 -*- import unittest, test.test_support +from test.script_helper import assert_python_ok, assert_python_failure import sys, os, cStringIO import struct import operator @@ -114,90 +115,65 @@ clear_check(exc) def test_exit(self): + # call with two arguments self.assertRaises(TypeError, sys.exit, 42, 42) # call without argument - try: - sys.exit(0) - except SystemExit, exc: - self.assertEqual(exc.code, 0) - except: - self.fail("wrong exception") - else: - self.fail("no exception") + rc, out, err = assert_python_ok('-c', 'import sys; sys.exit()') + self.assertEqual(rc, 0) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + + # call with integer argument + with self.assertRaises(SystemExit) as cm: + sys.exit(42) + self.assertEqual(cm.exception.code, 42) # call with tuple argument with one entry # entry will be unpacked - try: - sys.exit(42) - except SystemExit, exc: - self.assertEqual(exc.code, 42) - except: - self.fail("wrong exception") - else: - self.fail("no exception") - - # call with integer argument - try: + with self.assertRaises(SystemExit) as cm: sys.exit((42,)) - except SystemExit, exc: - self.assertEqual(exc.code, 42) - except: - self.fail("wrong exception") - else: - self.fail("no exception") + self.assertEqual(cm.exception.code, 42) # call with string argument - try: + with self.assertRaises(SystemExit) as cm: sys.exit("exit") - except SystemExit, exc: - self.assertEqual(exc.code, "exit") - except: - self.fail("wrong exception") - else: - self.fail("no exception") + self.assertEqual(cm.exception.code, "exit") # call with tuple argument with two entries - try: + with self.assertRaises(SystemExit) as cm: sys.exit((17, 23)) - except SystemExit, exc: - self.assertEqual(exc.code, (17, 23)) - except: - self.fail("wrong exception") - else: - self.fail("no exception") + self.assertEqual(cm.exception.code, (17, 23)) # test that the exit machinery handles SystemExits properly - import subprocess # both unnormalized... - rc = subprocess.call([sys.executable, "-c", - "raise SystemExit, 46"]) + rc, out, err = assert_python_failure('-c', 'raise SystemExit, 46') self.assertEqual(rc, 46) + self.assertEqual(out, b'') + self.assertEqual(err, b'') # ... and normalized - rc = subprocess.call([sys.executable, "-c", - "raise SystemExit(47)"]) + rc, out, err = assert_python_failure('-c', 'raise SystemExit(47)') self.assertEqual(rc, 47) + self.assertEqual(out, b'') + self.assertEqual(err, b'') - def check_exit_message(code, expected, env=None): - process = subprocess.Popen([sys.executable, "-c", code], - stderr=subprocess.PIPE, env=env) - stdout, stderr = process.communicate() - self.assertEqual(process.returncode, 1) - self.assertTrue(stderr.startswith(expected), - "%s doesn't start with %s" % (repr(stderr), repr(expected))) + def check_exit_message(code, expected, **env_vars): + rc, out, err = assert_python_failure('-c', code, **env_vars) + self.assertEqual(rc, 1) + self.assertEqual(out, b'') + self.assertTrue(err.startswith(expected), + "%s doesn't start with %s" % (repr(err), repr(expected))) - # test that stderr buffer if flushed before the exit message is written + # test that stderr buffer is flushed before the exit message is written # into stderr check_exit_message( r'import sys; sys.stderr.write("unflushed,"); sys.exit("message")', b"unflushed,message") # test that the unicode message is encoded to the stderr encoding - env = os.environ.copy() - env['PYTHONIOENCODING'] = 'latin-1' check_exit_message( r'import sys; sys.exit(u"h\xe9")', - b"h\xe9", env=env) + b"h\xe9", PYTHONIOENCODING='latin-1') def test_getdefaultencoding(self): if test.test_support.have_unicode: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -243,6 +243,10 @@ Tests ----- +- Issue #20510: Rewrote test_exit in test_sys to match existing comments, + use modern unittest features, and use helpers from test.script_helper + instead of using subprocess directly. Initial patch by Gareth Rees. + - Issue #20532: Tests which use _testcapi now are marked as CPython only. - Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 15:42:10 2014 From: python-checkins at python.org (zach.ware) Date: Tue, 18 Feb 2014 15:42:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTEw?= =?utf-8?q?=3A_Rewrote_test=5Fexit_in_test=5Fsys_to_match_existing_comment?= =?utf-8?q?s?= Message-ID: <3fT4XL0M0Cz7Lmr@mail.python.org> http://hg.python.org/cpython/rev/fa81f6ddd60e changeset: 89250:fa81f6ddd60e branch: 3.3 parent: 89241:b6d6ca792b64 user: Zachary Ware date: Tue Feb 18 08:39:04 2014 -0600 summary: Issue #20510: Rewrote test_exit in test_sys to match existing comments and to modernize. Patch by Gareth Rees. files: Lib/test/test_sys.py | 81 +++++++++++-------------------- Misc/NEWS | 4 + 2 files changed, 32 insertions(+), 53 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1,4 +1,5 @@ import unittest, test.support +from test.script_helper import assert_python_ok, assert_python_failure import sys, io, os import struct import subprocess @@ -86,74 +87,50 @@ # Python/pythonrun.c::PyErr_PrintEx() is tricky. def test_exit(self): - + # call with two arguments self.assertRaises(TypeError, sys.exit, 42, 42) # call without argument - try: - sys.exit(0) - except SystemExit as exc: - self.assertEqual(exc.code, 0) - except: - self.fail("wrong exception") - else: - self.fail("no exception") + rc, out, err = assert_python_ok('-c', 'import sys; sys.exit()') + self.assertEqual(rc, 0) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + + # call with integer argument + with self.assertRaises(SystemExit) as cm: + sys.exit(42) + self.assertEqual(cm.exception.code, 42) # call with tuple argument with one entry # entry will be unpacked - try: - sys.exit(42) - except SystemExit as exc: - self.assertEqual(exc.code, 42) - except: - self.fail("wrong exception") - else: - self.fail("no exception") - - # call with integer argument - try: + with self.assertRaises(SystemExit) as cm: sys.exit((42,)) - except SystemExit as exc: - self.assertEqual(exc.code, 42) - except: - self.fail("wrong exception") - else: - self.fail("no exception") + self.assertEqual(cm.exception.code, 42) # call with string argument - try: + with self.assertRaises(SystemExit) as cm: sys.exit("exit") - except SystemExit as exc: - self.assertEqual(exc.code, "exit") - except: - self.fail("wrong exception") - else: - self.fail("no exception") + self.assertEqual(cm.exception.code, "exit") # call with tuple argument with two entries - try: + with self.assertRaises(SystemExit) as cm: sys.exit((17, 23)) - except SystemExit as exc: - self.assertEqual(exc.code, (17, 23)) - except: - self.fail("wrong exception") - else: - self.fail("no exception") + self.assertEqual(cm.exception.code, (17, 23)) # test that the exit machinery handles SystemExits properly - rc = subprocess.call([sys.executable, "-c", - "raise SystemExit(47)"]) + rc, out, err = assert_python_failure('-c', 'raise SystemExit(47)') self.assertEqual(rc, 47) + self.assertEqual(out, b'') + self.assertEqual(err, b'') - def check_exit_message(code, expected, env=None): - process = subprocess.Popen([sys.executable, "-c", code], - stderr=subprocess.PIPE, env=env) - stdout, stderr = process.communicate() - self.assertEqual(process.returncode, 1) - self.assertTrue(stderr.startswith(expected), - "%s doesn't start with %s" % (ascii(stderr), ascii(expected))) + def check_exit_message(code, expected, **env_vars): + rc, out, err = assert_python_failure('-c', code, **env_vars) + self.assertEqual(rc, 1) + self.assertEqual(out, b'') + self.assertTrue(err.startswith(expected), + "%s doesn't start with %s" % (ascii(err), ascii(expected))) - # test that stderr buffer if flushed before the exit message is written + # test that stderr buffer is flushed before the exit message is written # into stderr check_exit_message( r'import sys; sys.stderr.write("unflushed,"); sys.exit("message")', @@ -167,11 +144,9 @@ # test that the unicode message is encoded to the stderr encoding # instead of the default encoding (utf8) - env = os.environ.copy() - env['PYTHONIOENCODING'] = 'latin-1' check_exit_message( r'import sys; sys.exit("h\xe9")', - b"h\xe9", env=env) + b"h\xe9", PYTHONIOENCODING='latin-1') def test_getdefaultencoding(self): self.assertRaises(TypeError, sys.getdefaultencoding, 42) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -110,6 +110,10 @@ Tests ----- +- Issue #20510: Rewrote test_exit in test_sys to match existing comments, + use modern unittest features, and use helpers from test.script_helper + instead of using subprocess directly. Patch by Gareth Rees. + - Issue #20532: Tests which use _testcapi are now marked as CPython only. - Issue #19920: Added tests for TarFile.list(). Based on patch by Vajrasky Kok. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 15:42:11 2014 From: python-checkins at python.org (zach.ware) Date: Tue, 18 Feb 2014 15:42:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320510=3A_Merge_with_3=2E3=2E?= Message-ID: <3fT4XM4K0Kz7Lmr@mail.python.org> http://hg.python.org/cpython/rev/2438fbf4ad9d changeset: 89251:2438fbf4ad9d parent: 89248:79e5bb0d9b8e parent: 89250:fa81f6ddd60e user: Zachary Ware date: Tue Feb 18 08:41:21 2014 -0600 summary: Issue #20510: Merge with 3.3. files: Lib/test/test_sys.py | 81 +++++++++++-------------------- Misc/NEWS | 4 + 2 files changed, 32 insertions(+), 53 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1,4 +1,5 @@ import unittest, test.support +from test.script_helper import assert_python_ok, assert_python_failure import sys, io, os import struct import subprocess @@ -89,74 +90,50 @@ # Python/pythonrun.c::PyErr_PrintEx() is tricky. def test_exit(self): - + # call with two arguments self.assertRaises(TypeError, sys.exit, 42, 42) # call without argument - try: - sys.exit(0) - except SystemExit as exc: - self.assertEqual(exc.code, 0) - except: - self.fail("wrong exception") - else: - self.fail("no exception") + rc, out, err = assert_python_ok('-c', 'import sys; sys.exit()') + self.assertEqual(rc, 0) + self.assertEqual(out, b'') + self.assertEqual(err, b'') + + # call with integer argument + with self.assertRaises(SystemExit) as cm: + sys.exit(42) + self.assertEqual(cm.exception.code, 42) # call with tuple argument with one entry # entry will be unpacked - try: - sys.exit(42) - except SystemExit as exc: - self.assertEqual(exc.code, 42) - except: - self.fail("wrong exception") - else: - self.fail("no exception") - - # call with integer argument - try: + with self.assertRaises(SystemExit) as cm: sys.exit((42,)) - except SystemExit as exc: - self.assertEqual(exc.code, 42) - except: - self.fail("wrong exception") - else: - self.fail("no exception") + self.assertEqual(cm.exception.code, 42) # call with string argument - try: + with self.assertRaises(SystemExit) as cm: sys.exit("exit") - except SystemExit as exc: - self.assertEqual(exc.code, "exit") - except: - self.fail("wrong exception") - else: - self.fail("no exception") + self.assertEqual(cm.exception.code, "exit") # call with tuple argument with two entries - try: + with self.assertRaises(SystemExit) as cm: sys.exit((17, 23)) - except SystemExit as exc: - self.assertEqual(exc.code, (17, 23)) - except: - self.fail("wrong exception") - else: - self.fail("no exception") + self.assertEqual(cm.exception.code, (17, 23)) # test that the exit machinery handles SystemExits properly - rc = subprocess.call([sys.executable, "-c", - "raise SystemExit(47)"]) + rc, out, err = assert_python_failure('-c', 'raise SystemExit(47)') self.assertEqual(rc, 47) + self.assertEqual(out, b'') + self.assertEqual(err, b'') - def check_exit_message(code, expected, env=None): - process = subprocess.Popen([sys.executable, "-c", code], - stderr=subprocess.PIPE, env=env) - stdout, stderr = process.communicate() - self.assertEqual(process.returncode, 1) - self.assertTrue(stderr.startswith(expected), - "%s doesn't start with %s" % (ascii(stderr), ascii(expected))) + def check_exit_message(code, expected, **env_vars): + rc, out, err = assert_python_failure('-c', code, **env_vars) + self.assertEqual(rc, 1) + self.assertEqual(out, b'') + self.assertTrue(err.startswith(expected), + "%s doesn't start with %s" % (ascii(err), ascii(expected))) - # test that stderr buffer if flushed before the exit message is written + # test that stderr buffer is flushed before the exit message is written # into stderr check_exit_message( r'import sys; sys.stderr.write("unflushed,"); sys.exit("message")', @@ -170,11 +147,9 @@ # test that the unicode message is encoded to the stderr encoding # instead of the default encoding (utf8) - env = os.environ.copy() - env['PYTHONIOENCODING'] = 'latin-1' check_exit_message( r'import sys; sys.exit("h\xe9")', - b"h\xe9", env=env) + b"h\xe9", PYTHONIOENCODING='latin-1') def test_getdefaultencoding(self): self.assertRaises(TypeError, sys.getdefaultencoding, 42) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -51,6 +51,10 @@ Tests ----- +- Issue #20510: Rewrote test_exit in test_sys to match existing comments, + use modern unittest features, and use helpers from test.script_helper + instead of using subprocess directly. Patch by Gareth Rees. + - Issue #20605: Make test_socket getaddrinfo OS X segfault test more robust. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 18:15:29 2014 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Feb 2014 18:15:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Add_support_for?= =?utf-8?q?_UNIX_Domain_Sockets=2E?= Message-ID: <3fT7xF0sDCz7LmK@mail.python.org> http://hg.python.org/cpython/rev/c27728212fcd changeset: 89252:c27728212fcd user: Yury Selivanov date: Tue Feb 18 12:15:06 2014 -0500 summary: asyncio: Add support for UNIX Domain Sockets. files: Lib/asyncio/base_events.py | 7 + Lib/asyncio/events.py | 26 + Lib/asyncio/streams.py | 39 +- Lib/asyncio/test_utils.py | 153 +++- Lib/asyncio/unix_events.py | 75 ++- Lib/test/test_asyncio/test_base_events.py | 2 +- Lib/test/test_asyncio/test_events.py | 353 ++++++--- Lib/test/test_asyncio/test_selector_events.py | 3 +- Lib/test/test_asyncio/test_streams.py | 215 ++++- Lib/test/test_asyncio/test_unix_events.py | 82 ++- 10 files changed, 750 insertions(+), 205 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -407,6 +407,13 @@ sock.setblocking(False) + transport, protocol = yield from self._create_connection_transport( + sock, protocol_factory, ssl, server_hostname) + return transport, protocol + + @tasks.coroutine + def _create_connection_transport(self, sock, protocol_factory, ssl, + server_hostname): protocol = protocol_factory() waiter = futures.Future(loop=self) if ssl: diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -220,6 +220,32 @@ """ raise NotImplementedError + def create_unix_connection(self, protocol_factory, path, *, + ssl=None, sock=None, + server_hostname=None): + raise NotImplementedError + + def create_unix_server(self, protocol_factory, path, *, + sock=None, backlog=100, ssl=None): + """A coroutine which creates a UNIX Domain Socket server. + + The return valud is a Server object, which can be used to stop + the service. + + path is a str, representing a file systsem path to bind the + server socket to. + + sock can optionally be specified in order to use a preexisting + socket object. + + backlog is the maximum number of queued connections passed to + listen() (defaults to 100). + + ssl can be set to an SSLContext to enable SSL over the + accepted connections. + """ + raise NotImplementedError + def create_datagram_endpoint(self, protocol_factory, local_addr=None, remote_addr=None, *, family=0, proto=0, flags=0): diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -1,9 +1,13 @@ """Stream-related things.""" __all__ = ['StreamReader', 'StreamWriter', 'StreamReaderProtocol', - 'open_connection', 'start_server', 'IncompleteReadError', + 'open_connection', 'start_server', + 'open_unix_connection', 'start_unix_server', + 'IncompleteReadError', ] +import socket + from . import events from . import futures from . import protocols @@ -93,6 +97,39 @@ return (yield from loop.create_server(factory, host, port, **kwds)) +if hasattr(socket, 'AF_UNIX'): + # UNIX Domain Sockets are supported on this platform + + @tasks.coroutine + 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( + lambda: protocol, path, **kwds) + writer = StreamWriter(transport, protocol, reader, loop) + return reader, writer + + + @tasks.coroutine + 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() + + def factory(): + reader = StreamReader(limit=limit, loop=loop) + protocol = StreamReaderProtocol(reader, client_connected_cb, + loop=loop) + return protocol + + return (yield from loop.create_unix_server(factory, path, **kwds)) + + class FlowControlMixin(protocols.Protocol): """Reusable flow control logic for StreamWriter.drain(). diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -4,12 +4,18 @@ import contextlib import io import os +import socket +import socketserver import sys +import tempfile import threading import time import unittest import unittest.mock + +from http.server import HTTPServer from wsgiref.simple_server import make_server, WSGIRequestHandler, WSGIServer + try: import ssl except ImportError: # pragma: no cover @@ -70,42 +76,51 @@ loop.run_forever() - at contextlib.contextmanager -def run_test_server(*, host='127.0.0.1', port=0, use_ssl=False): +class SilentWSGIRequestHandler(WSGIRequestHandler): - class SilentWSGIRequestHandler(WSGIRequestHandler): - def get_stderr(self): - return io.StringIO() + def get_stderr(self): + return io.StringIO() - def log_message(self, format, *args): + def log_message(self, format, *args): + pass + + +class SilentWSGIServer(WSGIServer): + + def handle_error(self, request, client_address): + pass + + +class SSLWSGIServerMixin: + + def finish_request(self, request, client_address): + # The relative location of our test directory (which + # contains the ssl key and certificate files) differs + # between the stdlib and stand-alone asyncio. + # Prefer our own if we can find it. + here = os.path.join(os.path.dirname(__file__), '..', 'tests') + if not os.path.isdir(here): + here = os.path.join(os.path.dirname(os.__file__), + 'test', 'test_asyncio') + keyfile = os.path.join(here, 'ssl_key.pem') + certfile = os.path.join(here, 'ssl_cert.pem') + ssock = ssl.wrap_socket(request, + keyfile=keyfile, + certfile=certfile, + server_side=True) + try: + self.RequestHandlerClass(ssock, client_address, self) + ssock.close() + except OSError: + # maybe socket has been closed by peer pass - class SilentWSGIServer(WSGIServer): - def handle_error(self, request, client_address): - pass - class SSLWSGIServer(SilentWSGIServer): - def finish_request(self, request, client_address): - # The relative location of our test directory (which - # contains the ssl key and certificate files) differs - # between the stdlib and stand-alone asyncio. - # Prefer our own if we can find it. - here = os.path.join(os.path.dirname(__file__), '..', 'tests') - if not os.path.isdir(here): - here = os.path.join(os.path.dirname(os.__file__), - 'test', 'test_asyncio') - keyfile = os.path.join(here, 'ssl_key.pem') - certfile = os.path.join(here, 'ssl_cert.pem') - ssock = ssl.wrap_socket(request, - keyfile=keyfile, - certfile=certfile, - server_side=True) - try: - self.RequestHandlerClass(ssock, client_address, self) - ssock.close() - except OSError: - # maybe socket has been closed by peer - pass +class SSLWSGIServer(SSLWSGIServerMixin, SilentWSGIServer): + pass + + +def _run_test_server(*, address, use_ssl=False, server_cls, server_ssl_cls): def app(environ, start_response): status = '200 OK' @@ -115,9 +130,9 @@ # Run the test WSGI server in a separate thread in order not to # interfere with event handling in the main thread - server_class = SSLWSGIServer if use_ssl else SilentWSGIServer - httpd = make_server(host, port, app, - server_class, SilentWSGIRequestHandler) + server_class = server_ssl_cls if use_ssl else server_cls + httpd = server_class(address, SilentWSGIRequestHandler) + httpd.set_app(app) httpd.address = httpd.server_address server_thread = threading.Thread(target=httpd.serve_forever) server_thread.start() @@ -129,6 +144,75 @@ server_thread.join() +if hasattr(socket, 'AF_UNIX'): + + class UnixHTTPServer(socketserver.UnixStreamServer, HTTPServer): + + def server_bind(self): + socketserver.UnixStreamServer.server_bind(self) + self.server_name = '127.0.0.1' + self.server_port = 80 + + + class UnixWSGIServer(UnixHTTPServer, WSGIServer): + + def server_bind(self): + UnixHTTPServer.server_bind(self) + self.setup_environ() + + def get_request(self): + request, client_addr = super().get_request() + # Code in the stdlib expects that get_request + # will return a socket and a tuple (host, port). + # However, this isn't true for UNIX sockets, + # as the second return value will be a path; + # hence we return some fake data sufficient + # to get the tests going + return request, ('127.0.0.1', '') + + + class SilentUnixWSGIServer(UnixWSGIServer): + + def handle_error(self, request, client_address): + pass + + + class UnixSSLWSGIServer(SSLWSGIServerMixin, SilentUnixWSGIServer): + pass + + + def gen_unix_socket_path(): + with tempfile.NamedTemporaryFile() as file: + return file.name + + + @contextlib.contextmanager + def unix_socket_path(): + path = gen_unix_socket_path() + try: + yield path + finally: + try: + os.unlink(path) + except OSError: + pass + + + @contextlib.contextmanager + def run_test_unix_server(*, use_ssl=False): + with unix_socket_path() as path: + yield from _run_test_server(address=path, use_ssl=use_ssl, + server_cls=SilentUnixWSGIServer, + server_ssl_cls=UnixSSLWSGIServer) + + + at contextlib.contextmanager +def run_test_server(*, host='127.0.0.1', port=0, use_ssl=False): + yield from _run_test_server(address=(host, port), use_ssl=use_ssl, + server_cls=SilentWSGIServer, + server_ssl_cls=SSLWSGIServer) + + def make_test_protocol(base): dct = {} for name in dir(base): @@ -275,5 +359,6 @@ def _write_to_self(self): pass + def MockCallback(**kwargs): return unittest.mock.Mock(spec=['__call__'], **kwargs) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -11,6 +11,7 @@ import threading +from . import base_events from . import base_subprocess from . import constants from . import events @@ -31,9 +32,9 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop): - """Unix event loop + """Unix event loop. - Adds signal handling to SelectorEventLoop + Adds signal handling and UNIX Domain Socket support to SelectorEventLoop. """ def __init__(self, selector=None): @@ -164,6 +165,76 @@ def _child_watcher_callback(self, pid, returncode, transp): self.call_soon_threadsafe(transp._process_exited, returncode) + @tasks.coroutine + def create_unix_connection(self, protocol_factory, path, *, + ssl=None, sock=None, + server_hostname=None): + assert server_hostname is None or isinstance(server_hostname, str) + if ssl: + if server_hostname is None: + raise ValueError( + 'you have to pass server_hostname when using ssl') + else: + if server_hostname is not None: + raise ValueError('server_hostname is only meaningful with ssl') + + if path is not None: + if sock is not None: + raise ValueError( + 'path and sock can not be specified at the same time') + + try: + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0) + sock.setblocking(False) + yield from self.sock_connect(sock, path) + except OSError: + if sock is not None: + sock.close() + raise + + else: + if sock is None: + raise ValueError('no path and sock were specified') + sock.setblocking(False) + + transport, protocol = yield from self._create_connection_transport( + sock, protocol_factory, ssl, server_hostname) + return transport, protocol + + @tasks.coroutine + 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') + + if path is not None: + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + + try: + sock.bind(path) + except OSError as exc: + 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) + raise OSError(errno.EADDRINUSE, msg) from None + else: + raise + else: + if sock is None: + raise ValueError( + 'path was not specified, and no sock specified') + + if sock.family != socket.AF_UNIX: + raise ValueError( + 'A UNIX Domain Socket was expected, got {!r}'.format(sock)) + + server = base_events.Server(self, [sock]) + sock.listen(backlog) + sock.setblocking(False) + self._start_serving(protocol_factory, sock, ssl, server) + return server + def _set_nonblocking(fd): flags = fcntl.fcntl(fd, fcntl.F_GETFL) diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -212,7 +212,7 @@ idx = -1 data = [10.0, 10.0, 10.3, 13.0] - self.loop._scheduled = [asyncio.TimerHandle(11.0, lambda:True, ())] + self.loop._scheduled = [asyncio.TimerHandle(11.0, lambda: True, ())] self.loop._run_once() self.assertEqual(logging.DEBUG, m_logger.log.call_args[0][0]) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -39,13 +39,14 @@ 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') -class MyProto(asyncio.Protocol): +class MyBaseProto(asyncio.Protocol): done = None def __init__(self, loop=None): @@ -59,7 +60,6 @@ self.transport = transport assert self.state == 'INITIAL', self.state self.state = 'CONNECTED' - transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') def data_received(self, data): assert self.state == 'CONNECTED', self.state @@ -76,6 +76,12 @@ self.done.set_result(None) +class MyProto(MyBaseProto): + def connection_made(self, transport): + super().connection_made(transport) + transport.write(b'GET / HTTP/1.0\r\nHost: example.com\r\n\r\n') + + class MyDatagramProto(asyncio.DatagramProtocol): done = None @@ -357,22 +363,30 @@ r.close() self.assertGreaterEqual(len(data), 200) + def _basetest_sock_client_ops(self, httpd, sock): + sock.setblocking(False) + self.loop.run_until_complete( + self.loop.sock_connect(sock, httpd.address)) + self.loop.run_until_complete( + self.loop.sock_sendall(sock, b'GET / HTTP/1.0\r\n\r\n')) + data = self.loop.run_until_complete( + self.loop.sock_recv(sock, 1024)) + # consume data + self.loop.run_until_complete( + self.loop.sock_recv(sock, 1024)) + sock.close() + self.assertTrue(data.startswith(b'HTTP/1.0 200 OK')) + def test_sock_client_ops(self): with test_utils.run_test_server() as httpd: sock = socket.socket() - sock.setblocking(False) - self.loop.run_until_complete( - self.loop.sock_connect(sock, httpd.address)) - self.loop.run_until_complete( - self.loop.sock_sendall(sock, b'GET / HTTP/1.0\r\n\r\n')) - data = self.loop.run_until_complete( - self.loop.sock_recv(sock, 1024)) - # consume data - self.loop.run_until_complete( - self.loop.sock_recv(sock, 1024)) - sock.close() + self._basetest_sock_client_ops(httpd, sock) - self.assertTrue(data.startswith(b'HTTP/1.0 200 OK')) + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_unix_sock_client_ops(self): + with test_utils.run_test_unix_server() as httpd: + sock = socket.socket(socket.AF_UNIX) + self._basetest_sock_client_ops(httpd, sock) def test_sock_client_fail(self): # Make sure that we will get an unused port @@ -485,16 +499,26 @@ self.loop.run_forever() self.assertEqual(caught, 1) + def _basetest_create_connection(self, connection_fut): + tr, pr = self.loop.run_until_complete(connection_fut) + self.assertIsInstance(tr, asyncio.Transport) + self.assertIsInstance(pr, asyncio.Protocol) + self.loop.run_until_complete(pr.done) + self.assertGreater(pr.nbytes, 0) + tr.close() + def test_create_connection(self): with test_utils.run_test_server() as httpd: - f = self.loop.create_connection( + conn_fut = self.loop.create_connection( lambda: MyProto(loop=self.loop), *httpd.address) - tr, pr = self.loop.run_until_complete(f) - self.assertIsInstance(tr, asyncio.Transport) - self.assertIsInstance(pr, asyncio.Protocol) - self.loop.run_until_complete(pr.done) - self.assertGreater(pr.nbytes, 0) - tr.close() + self._basetest_create_connection(conn_fut) + + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_create_unix_connection(self): + with test_utils.run_test_unix_server() as httpd: + conn_fut = self.loop.create_unix_connection( + lambda: MyProto(loop=self.loop), httpd.address) + self._basetest_create_connection(conn_fut) def test_create_connection_sock(self): with test_utils.run_test_server() as httpd: @@ -524,20 +548,37 @@ self.assertGreater(pr.nbytes, 0) tr.close() + def _basetest_create_ssl_connection(self, connection_fut): + tr, pr = self.loop.run_until_complete(connection_fut) + self.assertIsInstance(tr, asyncio.Transport) + self.assertIsInstance(pr, asyncio.Protocol) + self.assertTrue('ssl' in tr.__class__.__name__.lower()) + self.assertIsNotNone(tr.get_extra_info('sockname')) + self.loop.run_until_complete(pr.done) + self.assertGreater(pr.nbytes, 0) + tr.close() + @unittest.skipIf(ssl is None, 'No ssl module') def test_create_ssl_connection(self): with test_utils.run_test_server(use_ssl=True) as httpd: - f = self.loop.create_connection( - lambda: MyProto(loop=self.loop), *httpd.address, + conn_fut = self.loop.create_connection( + lambda: MyProto(loop=self.loop), + *httpd.address, ssl=test_utils.dummy_ssl_context()) - tr, pr = self.loop.run_until_complete(f) - self.assertIsInstance(tr, asyncio.Transport) - self.assertIsInstance(pr, asyncio.Protocol) - self.assertTrue('ssl' in tr.__class__.__name__.lower()) - self.assertIsNotNone(tr.get_extra_info('sockname')) - self.loop.run_until_complete(pr.done) - self.assertGreater(pr.nbytes, 0) - tr.close() + + self._basetest_create_ssl_connection(conn_fut) + + @unittest.skipIf(ssl is None, 'No ssl module') + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_create_ssl_unix_connection(self): + with test_utils.run_test_unix_server(use_ssl=True) as httpd: + conn_fut = self.loop.create_unix_connection( + lambda: MyProto(loop=self.loop), + httpd.address, + ssl=test_utils.dummy_ssl_context(), + server_hostname='127.0.0.1') + + self._basetest_create_ssl_connection(conn_fut) def test_create_connection_local_addr(self): with test_utils.run_test_server() as httpd: @@ -561,14 +602,8 @@ self.assertIn(str(httpd.address), cm.exception.strerror) def test_create_server(self): - proto = None - - def factory(): - nonlocal proto - proto = MyProto() - return proto - - f = self.loop.create_server(factory, '0.0.0.0', 0) + proto = MyProto() + f = self.loop.create_server(lambda: proto, '0.0.0.0', 0) server = self.loop.run_until_complete(f) self.assertEqual(len(server.sockets), 1) sock = server.sockets[0] @@ -605,38 +640,76 @@ # close server server.close() - def _make_ssl_server(self, factory, certfile, keyfile=None): + def _make_unix_server(self, factory, **kwargs): + path = test_utils.gen_unix_socket_path() + self.addCleanup(lambda: os.path.exists(path) and os.unlink(path)) + + f = self.loop.create_unix_server(factory, path, **kwargs) + server = self.loop.run_until_complete(f) + + return server, path + + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_create_unix_server(self): + proto = MyProto() + server, path = self._make_unix_server(lambda: proto) + self.assertEqual(len(server.sockets), 1) + + client = socket.socket(socket.AF_UNIX) + client.connect(path) + client.sendall(b'xxx') + test_utils.run_briefly(self.loop) + test_utils.run_until(self.loop, lambda: proto is not None, 10) + + self.assertIsInstance(proto, MyProto) + self.assertEqual('INITIAL', proto.state) + test_utils.run_briefly(self.loop) + self.assertEqual('CONNECTED', proto.state) + test_utils.run_until(self.loop, lambda: proto.nbytes > 0, + timeout=10) + self.assertEqual(3, proto.nbytes) + + # close connection + proto.transport.close() + test_utils.run_briefly(self.loop) # windows iocp + + self.assertEqual('CLOSED', proto.state) + + # the client socket must be closed after to avoid ECONNRESET upon + # recv()/send() on the serving socket + client.close() + + # close server + server.close() + + def _create_ssl_context(self, certfile, keyfile=None): sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23) sslcontext.options |= ssl.OP_NO_SSLv2 sslcontext.load_cert_chain(certfile, keyfile) + return sslcontext - f = self.loop.create_server( - factory, '127.0.0.1', 0, ssl=sslcontext) + def _make_ssl_server(self, factory, certfile, keyfile=None): + sslcontext = self._create_ssl_context(certfile, keyfile) + f = self.loop.create_server(factory, '127.0.0.1', 0, ssl=sslcontext) server = self.loop.run_until_complete(f) + sock = server.sockets[0] host, port = sock.getsockname() self.assertEqual(host, '127.0.0.1') return server, host, port + def _make_ssl_unix_server(self, factory, certfile, keyfile=None): + sslcontext = self._create_ssl_context(certfile, keyfile) + return self._make_unix_server(factory, ssl=sslcontext) + @unittest.skipIf(ssl is None, 'No ssl module') def test_create_server_ssl(self): - proto = None + proto = MyProto(loop=self.loop) + server, host, port = self._make_ssl_server( + lambda: proto, ONLYCERT, ONLYKEY) - class ClientMyProto(MyProto): - def connection_made(self, transport): - self.transport = transport - assert self.state == 'INITIAL', self.state - self.state = 'CONNECTED' - - def factory(): - nonlocal proto - proto = MyProto(loop=self.loop) - return proto - - server, host, port = self._make_ssl_server(factory, ONLYCERT, ONLYKEY) - - f_c = self.loop.create_connection(ClientMyProto, host, port, + f_c = self.loop.create_connection(MyBaseProto, host, port, ssl=test_utils.dummy_ssl_context()) client, pr = self.loop.run_until_complete(f_c) @@ -667,16 +740,45 @@ server.close() @unittest.skipIf(ssl is None, 'No ssl module') + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_create_unix_server_ssl(self): + proto = MyProto(loop=self.loop) + server, path = self._make_ssl_unix_server( + lambda: proto, ONLYCERT, ONLYKEY) + + f_c = self.loop.create_unix_connection( + MyBaseProto, path, ssl=test_utils.dummy_ssl_context(), + server_hostname='') + + client, pr = self.loop.run_until_complete(f_c) + + client.write(b'xxx') + test_utils.run_briefly(self.loop) + self.assertIsInstance(proto, MyProto) + test_utils.run_briefly(self.loop) + self.assertEqual('CONNECTED', proto.state) + test_utils.run_until(self.loop, lambda: proto.nbytes > 0, + timeout=10) + self.assertEqual(3, proto.nbytes) + + # close connection + proto.transport.close() + self.loop.run_until_complete(proto.done) + self.assertEqual('CLOSED', proto.state) + + # the client socket must be closed after to avoid ECONNRESET upon + # recv()/send() on the serving socket + client.close() + + # stop serving + server.close() + + @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(HAS_SNI, 'No SNI support in ssl module') def test_create_server_ssl_verify_failed(self): - proto = None - - def factory(): - nonlocal proto - proto = MyProto(loop=self.loop) - return proto - - server, host, port = self._make_ssl_server(factory, SIGNED_CERTFILE) + proto = MyProto(loop=self.loop) + server, host, port = self._make_ssl_server( + lambda: proto, SIGNED_CERTFILE) sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_SSLv23) sslcontext_client.options |= ssl.OP_NO_SSLv2 @@ -697,15 +799,36 @@ @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(HAS_SNI, 'No SNI support in ssl module') + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + 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) + + sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + sslcontext_client.options |= ssl.OP_NO_SSLv2 + sslcontext_client.verify_mode = ssl.CERT_REQUIRED + if hasattr(sslcontext_client, 'check_hostname'): + sslcontext_client.check_hostname = True + + # no CA loaded + f_c = self.loop.create_unix_connection(MyProto, path, + ssl=sslcontext_client, + server_hostname='invalid') + with self.assertRaisesRegex(ssl.SSLError, + 'certificate verify failed '): + self.loop.run_until_complete(f_c) + + # close connection + self.assertIsNone(proto.transport) + server.close() + + @unittest.skipIf(ssl is None, 'No ssl module') + @unittest.skipUnless(HAS_SNI, 'No SNI support in ssl module') def test_create_server_ssl_match_failed(self): - proto = None - - def factory(): - nonlocal proto - proto = MyProto(loop=self.loop) - return proto - - server, host, port = self._make_ssl_server(factory, SIGNED_CERTFILE) + proto = MyProto(loop=self.loop) + server, host, port = self._make_ssl_server( + lambda: proto, SIGNED_CERTFILE) sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_SSLv23) sslcontext_client.options |= ssl.OP_NO_SSLv2 @@ -729,15 +852,36 @@ @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(HAS_SNI, 'No SNI support in ssl module') + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_create_unix_server_ssl_verified(self): + proto = MyProto(loop=self.loop) + server, path = self._make_ssl_unix_server( + lambda: proto, SIGNED_CERTFILE) + + sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + sslcontext_client.options |= ssl.OP_NO_SSLv2 + sslcontext_client.verify_mode = ssl.CERT_REQUIRED + sslcontext_client.load_verify_locations(cafile=SIGNING_CA) + if hasattr(sslcontext_client, 'check_hostname'): + sslcontext_client.check_hostname = True + + # Connection succeeds with correct CA and server hostname. + f_c = self.loop.create_unix_connection(MyProto, path, + ssl=sslcontext_client, + server_hostname='localhost') + client, pr = self.loop.run_until_complete(f_c) + + # close connection + proto.transport.close() + client.close() + server.close() + + @unittest.skipIf(ssl is None, 'No ssl module') + @unittest.skipUnless(HAS_SNI, 'No SNI support in ssl module') def test_create_server_ssl_verified(self): - proto = None - - def factory(): - nonlocal proto - proto = MyProto(loop=self.loop) - return proto - - server, host, port = self._make_ssl_server(factory, SIGNED_CERTFILE) + proto = MyProto(loop=self.loop) + server, host, port = self._make_ssl_server( + lambda: proto, SIGNED_CERTFILE) sslcontext_client = ssl.SSLContext(ssl.PROTOCOL_SSLv23) sslcontext_client.options |= ssl.OP_NO_SSLv2 @@ -915,19 +1059,15 @@ @unittest.skipUnless(sys.platform != 'win32', "Don't support pipes for Windows") def test_read_pipe(self): - proto = None - - def factory(): - nonlocal proto - proto = MyReadPipeProto(loop=self.loop) - return proto + proto = MyReadPipeProto(loop=self.loop) rpipe, wpipe = os.pipe() pipeobj = io.open(rpipe, 'rb', 1024) @asyncio.coroutine def connect(): - t, p = yield from self.loop.connect_read_pipe(factory, pipeobj) + t, p = yield from self.loop.connect_read_pipe( + lambda: proto, pipeobj) self.assertIs(p, proto) self.assertIs(t, proto.transport) self.assertEqual(['INITIAL', 'CONNECTED'], proto.state) @@ -959,19 +1099,14 @@ # 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): - proto = None - - def factory(): - nonlocal proto - proto = MyReadPipeProto(loop=self.loop) - return proto + proto = MyReadPipeProto(loop=self.loop) 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(factory, + t, p = yield from self.loop.connect_read_pipe(lambda: proto, master_read_obj) self.assertIs(p, proto) self.assertIs(t, proto.transport) @@ -999,21 +1134,17 @@ @unittest.skipUnless(sys.platform != 'win32', "Don't support pipes for Windows") def test_write_pipe(self): - proto = None + proto = MyWritePipeProto(loop=self.loop) transport = None - def factory(): - nonlocal proto - proto = MyWritePipeProto(loop=self.loop) - return proto - rpipe, wpipe = os.pipe() pipeobj = io.open(wpipe, 'wb', 1024) @asyncio.coroutine def connect(): nonlocal transport - t, p = yield from self.loop.connect_write_pipe(factory, pipeobj) + t, p = yield from self.loop.connect_write_pipe( + lambda: proto, pipeobj) self.assertIs(p, proto) self.assertIs(t, proto.transport) self.assertEqual('CONNECTED', proto.state) @@ -1045,21 +1176,16 @@ @unittest.skipUnless(sys.platform != 'win32', "Don't support pipes for Windows") def test_write_pipe_disconnect_on_close(self): - proto = None + proto = MyWritePipeProto(loop=self.loop) transport = None - def factory(): - nonlocal proto - proto = MyWritePipeProto(loop=self.loop) - return proto - rsock, wsock = test_utils.socketpair() pipeobj = io.open(wsock.detach(), 'wb', 1024) @asyncio.coroutine def connect(): nonlocal transport - t, p = yield from self.loop.connect_write_pipe(factory, + t, p = yield from self.loop.connect_write_pipe(lambda: proto, pipeobj) self.assertIs(p, proto) self.assertIs(t, proto.transport) @@ -1084,21 +1210,16 @@ # older than 10.6 (Snow Leopard) @support.requires_mac_ver(10, 6) def test_write_pty(self): - proto = None + proto = MyWritePipeProto(loop=self.loop) transport = None - def factory(): - nonlocal proto - proto = MyWritePipeProto(loop=self.loop) - return proto - master, slave = os.openpty() slave_write_obj = io.open(slave, 'wb', 0) @asyncio.coroutine def connect(): nonlocal transport - t, p = yield from self.loop.connect_write_pipe(factory, + t, p = yield from self.loop.connect_write_pipe(lambda: proto, slave_write_obj) self.assertIs(p, proto) self.assertIs(t, proto.transport) diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -55,7 +55,8 @@ self.loop.remove_reader = unittest.mock.Mock() self.loop.remove_writer = unittest.mock.Mock() waiter = asyncio.Future(loop=self.loop) - transport = self.loop._make_ssl_transport(m, asyncio.Protocol(), m, waiter) + transport = self.loop._make_ssl_transport( + m, asyncio.Protocol(), m, waiter) self.assertIsInstance(transport, _SelectorSslTransport) @unittest.mock.patch('asyncio.selector_events.ssl', None) diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -1,6 +1,8 @@ """Tests for streams.py.""" +import functools import gc +import socket import unittest import unittest.mock try: @@ -32,48 +34,85 @@ stream = asyncio.StreamReader() self.assertIs(stream._loop, m_events.get_event_loop.return_value) + def _basetest_open_connection(self, open_connection_fut): + reader, writer = self.loop.run_until_complete(open_connection_fut) + writer.write(b'GET / HTTP/1.0\r\n\r\n') + f = reader.readline() + data = self.loop.run_until_complete(f) + self.assertEqual(data, b'HTTP/1.0 200 OK\r\n') + f = reader.read() + data = self.loop.run_until_complete(f) + self.assertTrue(data.endswith(b'\r\n\r\nTest message')) + writer.close() + def test_open_connection(self): with test_utils.run_test_server() as httpd: - f = asyncio.open_connection(*httpd.address, loop=self.loop) - reader, writer = self.loop.run_until_complete(f) - writer.write(b'GET / HTTP/1.0\r\n\r\n') - f = reader.readline() - data = self.loop.run_until_complete(f) - self.assertEqual(data, b'HTTP/1.0 200 OK\r\n') - f = reader.read() - data = self.loop.run_until_complete(f) - self.assertTrue(data.endswith(b'\r\n\r\nTest message')) + conn_fut = asyncio.open_connection(*httpd.address, + loop=self.loop) + self._basetest_open_connection(conn_fut) - writer.close() + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_open_unix_connection(self): + with test_utils.run_test_unix_server() as httpd: + conn_fut = asyncio.open_unix_connection(httpd.address, + loop=self.loop) + self._basetest_open_connection(conn_fut) + + def _basetest_open_connection_no_loop_ssl(self, open_connection_fut): + try: + reader, writer = self.loop.run_until_complete(open_connection_fut) + finally: + asyncio.set_event_loop(None) + writer.write(b'GET / HTTP/1.0\r\n\r\n') + f = reader.read() + data = self.loop.run_until_complete(f) + self.assertTrue(data.endswith(b'\r\n\r\nTest message')) + + writer.close() @unittest.skipIf(ssl is None, 'No ssl module') def test_open_connection_no_loop_ssl(self): with test_utils.run_test_server(use_ssl=True) as httpd: - try: - asyncio.set_event_loop(self.loop) - f = asyncio.open_connection(*httpd.address, - ssl=test_utils.dummy_ssl_context()) - reader, writer = self.loop.run_until_complete(f) - finally: - asyncio.set_event_loop(None) - writer.write(b'GET / HTTP/1.0\r\n\r\n') - f = reader.read() - data = self.loop.run_until_complete(f) - self.assertTrue(data.endswith(b'\r\n\r\nTest message')) + conn_fut = asyncio.open_connection( + *httpd.address, + ssl=test_utils.dummy_ssl_context(), + loop=self.loop) - writer.close() + self._basetest_open_connection_no_loop_ssl(conn_fut) + + @unittest.skipIf(ssl is None, 'No ssl module') + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_open_unix_connection_no_loop_ssl(self): + with test_utils.run_test_unix_server(use_ssl=True) as httpd: + conn_fut = asyncio.open_unix_connection( + httpd.address, + ssl=test_utils.dummy_ssl_context(), + server_hostname='', + loop=self.loop) + + self._basetest_open_connection_no_loop_ssl(conn_fut) + + def _basetest_open_connection_error(self, open_connection_fut): + reader, writer = self.loop.run_until_complete(open_connection_fut) + writer._protocol.connection_lost(ZeroDivisionError()) + f = reader.read() + with self.assertRaises(ZeroDivisionError): + self.loop.run_until_complete(f) + writer.close() + test_utils.run_briefly(self.loop) def test_open_connection_error(self): with test_utils.run_test_server() as httpd: - f = asyncio.open_connection(*httpd.address, loop=self.loop) - reader, writer = self.loop.run_until_complete(f) - writer._protocol.connection_lost(ZeroDivisionError()) - f = reader.read() - with self.assertRaises(ZeroDivisionError): - self.loop.run_until_complete(f) + conn_fut = asyncio.open_connection(*httpd.address, + loop=self.loop) + self._basetest_open_connection_error(conn_fut) - writer.close() - test_utils.run_briefly(self.loop) + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_open_unix_connection_error(self): + with test_utils.run_test_unix_server() as httpd: + conn_fut = asyncio.open_unix_connection(httpd.address, + loop=self.loop) + self._basetest_open_connection_error(conn_fut) def test_feed_empty_data(self): stream = asyncio.StreamReader(loop=self.loop) @@ -415,10 +454,86 @@ client_writer.write(data) def start(self): + sock = socket.socket() + sock.bind(('127.0.0.1', 0)) self.server = self.loop.run_until_complete( asyncio.start_server(self.handle_client, - '127.0.0.1', 12345, + sock=sock, loop=self.loop)) + return sock.getsockname() + + def handle_client_callback(self, client_reader, client_writer): + task = asyncio.Task(client_reader.readline(), loop=self.loop) + + def done(task): + client_writer.write(task.result()) + + task.add_done_callback(done) + + def start_callback(self): + sock = socket.socket() + sock.bind(('127.0.0.1', 0)) + addr = sock.getsockname() + sock.close() + self.server = self.loop.run_until_complete( + asyncio.start_server(self.handle_client_callback, + host=addr[0], port=addr[1], + loop=self.loop)) + return addr + + def stop(self): + if self.server is not None: + self.server.close() + self.loop.run_until_complete(self.server.wait_closed()) + self.server = None + + @asyncio.coroutine + def client(addr): + reader, writer = yield from asyncio.open_connection( + *addr, loop=self.loop) + # send a line + writer.write(b"hello world!\n") + # read it back + msgback = yield from reader.readline() + writer.close() + return msgback + + # test the server variant with a coroutine as client handler + server = MyServer(self.loop) + addr = server.start() + msg = self.loop.run_until_complete(asyncio.Task(client(addr), + loop=self.loop)) + server.stop() + self.assertEqual(msg, b"hello world!\n") + + # test the server variant with a callback as client handler + server = MyServer(self.loop) + addr = server.start_callback() + msg = self.loop.run_until_complete(asyncio.Task(client(addr), + loop=self.loop)) + server.stop() + self.assertEqual(msg, b"hello world!\n") + + @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') + def test_start_unix_server(self): + + class MyServer: + + def __init__(self, loop, path): + self.server = None + self.loop = loop + self.path = path + + @asyncio.coroutine + def handle_client(self, client_reader, client_writer): + data = yield from client_reader.readline() + client_writer.write(data) + + def start(self): + self.server = self.loop.run_until_complete( + asyncio.start_unix_server(self.handle_client, + path=self.path, + loop=self.loop)) def handle_client_callback(self, client_reader, client_writer): task = asyncio.Task(client_reader.readline(), loop=self.loop) @@ -430,9 +545,9 @@ def start_callback(self): self.server = self.loop.run_until_complete( - asyncio.start_server(self.handle_client_callback, - '127.0.0.1', 12345, - loop=self.loop)) + asyncio.start_unix_server(self.handle_client_callback, + path=self.path, + loop=self.loop)) def stop(self): if self.server is not None: @@ -441,9 +556,9 @@ self.server = None @asyncio.coroutine - def client(): - reader, writer = yield from asyncio.open_connection( - '127.0.0.1', 12345, loop=self.loop) + def client(path): + reader, writer = yield from asyncio.open_unix_connection( + path, loop=self.loop) # send a line writer.write(b"hello world!\n") # read it back @@ -452,20 +567,22 @@ return msgback # test the server variant with a coroutine as client handler - server = MyServer(self.loop) - server.start() - msg = self.loop.run_until_complete(asyncio.Task(client(), - loop=self.loop)) - server.stop() - self.assertEqual(msg, b"hello world!\n") + with test_utils.unix_socket_path() as path: + server = MyServer(self.loop, path) + server.start() + msg = self.loop.run_until_complete(asyncio.Task(client(path), + loop=self.loop)) + server.stop() + self.assertEqual(msg, b"hello world!\n") # test the server variant with a callback as client handler - server = MyServer(self.loop) - server.start_callback() - msg = self.loop.run_until_complete(asyncio.Task(client(), - loop=self.loop)) - server.stop() - self.assertEqual(msg, b"hello world!\n") + with test_utils.unix_socket_path() as path: + server = MyServer(self.loop, path) + server.start_callback() + msg = self.loop.run_until_complete(asyncio.Task(client(path), + loop=self.loop)) + server.stop() + self.assertEqual(msg, b"hello world!\n") if __name__ == '__main__': diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -7,8 +7,10 @@ import os import pprint import signal +import socket import stat import sys +import tempfile import threading import unittest import unittest.mock @@ -24,7 +26,7 @@ @unittest.skipUnless(signal, 'Signals are not supported') -class SelectorEventLoopTests(unittest.TestCase): +class SelectorEventLoopSignalTests(unittest.TestCase): def setUp(self): self.loop = asyncio.SelectorEventLoop() @@ -200,6 +202,84 @@ m_signal.set_wakeup_fd.assert_called_once_with(-1) + at unittest.skipUnless(hasattr(socket, 'AF_UNIX'), + 'UNIX Sockets are not supported') +class SelectorEventLoopUnixSocketTests(unittest.TestCase): + + def setUp(self): + self.loop = asyncio.SelectorEventLoop() + asyncio.set_event_loop(None) + + def tearDown(self): + self.loop.close() + + def test_create_unix_server_existing_path_sock(self): + with test_utils.unix_socket_path() as path: + sock = socket.socket(socket.AF_UNIX) + sock.bind(path) + + coro = self.loop.create_unix_server(lambda: None, path) + with self.assertRaisesRegexp(OSError, + 'Address.*is already in use'): + self.loop.run_until_complete(coro) + + def test_create_unix_server_existing_path_nonsock(self): + with tempfile.NamedTemporaryFile() as file: + coro = self.loop.create_unix_server(lambda: None, file.name) + with self.assertRaisesRegexp(OSError, + 'Address.*is already in use'): + self.loop.run_until_complete(coro) + + def test_create_unix_server_ssl_bool(self): + coro = self.loop.create_unix_server(lambda: None, path='spam', + ssl=True) + with self.assertRaisesRegex(TypeError, + 'ssl argument must be an SSLContext'): + self.loop.run_until_complete(coro) + + def test_create_unix_server_nopath_nosock(self): + coro = self.loop.create_unix_server(lambda: None, path=None) + with self.assertRaisesRegex(ValueError, + 'path was not specified, and no sock'): + self.loop.run_until_complete(coro) + + def test_create_unix_server_path_inetsock(self): + coro = self.loop.create_unix_server(lambda: None, path=None, + sock=socket.socket()) + with self.assertRaisesRegex(ValueError, + 'A UNIX Domain Socket was expected'): + self.loop.run_until_complete(coro) + + def test_create_unix_connection_path_sock(self): + coro = self.loop.create_unix_connection( + lambda: None, '/dev/null', sock=object()) + with self.assertRaisesRegex(ValueError, 'path and sock can not be'): + self.loop.run_until_complete(coro) + + def test_create_unix_connection_nopath_nosock(self): + coro = self.loop.create_unix_connection( + lambda: None, None) + with self.assertRaisesRegex(ValueError, + 'no path and sock were specified'): + self.loop.run_until_complete(coro) + + def test_create_unix_connection_nossl_serverhost(self): + coro = self.loop.create_unix_connection( + lambda: None, '/dev/null', server_hostname='spam') + with self.assertRaisesRegex(ValueError, + 'server_hostname is only meaningful'): + self.loop.run_until_complete(coro) + + def test_create_unix_connection_ssl_noserverhost(self): + coro = self.loop.create_unix_connection( + lambda: None, '/dev/null', ssl=True) + + with self.assertRaisesRegexp( + ValueError, 'you have to pass server_hostname when using ssl'): + + self.loop.run_until_complete(coro) + + class UnixReadPipeTransportTests(unittest.TestCase): def setUp(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 18:22:07 2014 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Feb 2014 18:22:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Misc/NEWS=3A_Add_a_news_it?= =?utf-8?q?em_for_UNIX_Sockets_support_in_asyncio=2E_Cleanup_WS=2E?= Message-ID: <3fT84v518kz7Ljh@mail.python.org> http://hg.python.org/cpython/rev/d6c7d1f18915 changeset: 89253:d6c7d1f18915 user: Yury Selivanov date: Tue Feb 18 12:21:57 2014 -0500 summary: Misc/NEWS: Add a news item for UNIX Sockets support in asyncio. Cleanup WS. files: Misc/NEWS | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,13 +41,17 @@ Based on patch by Stephen Tu. - Issue #8478: Untokenizer.compat processes first token from iterator input. - Patch based on lines from Georg Brandl, Eric Snow, and Gareth Rees. + Patch based on lines from Georg Brandl, Eric Snow, and Gareth Rees. - Issue #20594: Avoid name clash with the libc function posix_close. - Issue #19856: shutil.move() failed to move a directory to other directory on Windows if source name ends with os.altsep. +- Issue #20673: Implement support for UNIX Domain Sockets in asyncio. + New APIs: loop.create_unix_connection(), loop.create_unix_server(), + streams.open_unix_connection(), and streams.start_unix_server(). + Tests ----- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 18:35:28 2014 From: python-checkins at python.org (zach.ware) Date: Tue, 18 Feb 2014 18:35:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNjA5?= =?utf-8?q?=3A_Fix_building_64-bit_binaries_on_32-bit_Windows=2E?= Message-ID: <3fT8NJ4nfgzRSS@mail.python.org> http://hg.python.org/cpython/rev/d610a2740b5f changeset: 89254:d610a2740b5f branch: 3.3 parent: 89250:fa81f6ddd60e user: Zachary Ware date: Tue Feb 18 11:33:18 2014 -0600 summary: Issue #20609: Fix building 64-bit binaries on 32-bit Windows. files: Misc/NEWS | 6 +++ PCbuild/pythoncore.vcxproj | 48 +++++++++++++++++++++---- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -131,6 +131,12 @@ - Issue #20488: Importlib is no longer *an* implementation of import, it's *the* implementation. +Build +----- + +- Issue #20609: Restored the ability to build 64-bit Windows binaries on + 32-bit Windows, which was broken by the change in issue #19788. + What's New in Python 3.3.4? =========================== diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -182,7 +182,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -213,7 +217,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -244,7 +252,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -278,7 +290,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -307,7 +323,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -339,7 +359,11 @@ MachineX64 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -368,7 +392,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -400,7 +428,11 @@ MachineX64 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 18:35:30 2014 From: python-checkins at python.org (zach.ware) Date: Tue, 18 Feb 2014 18:35:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320609=3A_Merge_with_3=2E3=2E?= Message-ID: <3fT8NL0ccdz7LnL@mail.python.org> http://hg.python.org/cpython/rev/69d13cdc4eeb changeset: 89255:69d13cdc4eeb parent: 89253:d6c7d1f18915 parent: 89254:d610a2740b5f user: Zachary Ware date: Tue Feb 18 11:35:15 2014 -0600 summary: Issue #20609: Merge with 3.3. files: Misc/NEWS | 6 +++ PCbuild/pythoncore.vcxproj | 48 +++++++++++++++++++++---- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,12 @@ - Issue #20605: Make test_socket getaddrinfo OS X segfault test more robust. +Build +----- + +- Issue #20609: Restored the ability to build 64-bit Windows binaries on + 32-bit Windows, which was broken by the change in issue #19788. + What's New in Python 3.4.0 release candidate 1? =============================================== diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -182,7 +182,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -213,7 +217,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -244,7 +252,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -278,7 +290,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -307,7 +323,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -339,7 +359,11 @@ MachineX64 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -368,7 +392,11 @@ 0x1e000000 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... @@ -400,7 +428,11 @@ MachineX64 - $(KillPythonExe) + $(KillPythonExe) +IF %ERRORLEVEL% NEQ 0 ( + echo kill_python: warning: could not kill running Pythons, exit code %ERRORLEVEL% + exit /b 0 +) Killing any running $(PythonExe) instances... -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 18:50:08 2014 From: python-checkins at python.org (yury.selivanov) Date: Tue, 18 Feb 2014 18:50:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Mangle_=5F=5Fparameters_in?= =?utf-8?q?_=5F=5Fannotations=5F=5F_dict_properly=2E_Issue_=2320625=2E?= Message-ID: <3fT8jD4qWZz7Ln9@mail.python.org> http://hg.python.org/cpython/rev/a63327162063 changeset: 89256:a63327162063 user: Yury Selivanov date: Tue Feb 18 12:49:41 2014 -0500 summary: Mangle __parameters in __annotations__ dict properly. Issue #20625. files: Doc/whatsnew/3.4.rst | 4 ++++ Lib/test/test_grammar.py | 7 +++++++ Lib/test/test_inspect.py | 16 ++++++++++++++++ Misc/NEWS | 3 +++ Python/compile.c | 8 +++++++- 5 files changed, 37 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1781,6 +1781,10 @@ perpetually alive (for example, database connections kept in thread-local storage). (:issue:`17094`.) +* Parameter names in ``__annotations__`` dict are now mangled properly, + similarly to ``__kwdefaults__``. (Contributed by Yury Selivanov in + :issue:`20625`). + Changes in the C API -------------------- diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -314,6 +314,13 @@ self.assertEqual(f.__annotations__, {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9, 'k': 11, 'return': 12}) + # Check for issue #20625 -- annotations mangling + class Spam: + def f(self, *, __kw:1): + pass + class Ham(Spam): pass + self.assertEquals(Spam.f.__annotations__, {'_Spam__kw': 1}) + self.assertEquals(Ham.f.__annotations__, {'_Spam__kw': 1}) # Check for SF Bug #1697248 - mixing decorators and a return annotation def null(x): return x @null diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -2390,6 +2390,22 @@ self.assertEqual(sig.return_annotation, 42) self.assertEqual(sig, inspect.signature(test)) + def test_signature_on_mangled_parameters(self): + class Spam: + def foo(self, __p1:1=2, *, __p2:2=3): + pass + class Ham(Spam): + pass + + self.assertEqual(self.signature(Spam.foo), + ((('self', ..., ..., "positional_or_keyword"), + ('_Spam__p1', 2, 1, "positional_or_keyword"), + ('_Spam__p2', 3, 2, "keyword_only")), + ...)) + + self.assertEqual(self.signature(Spam.foo), + self.signature(Ham.foo)) + class TestParameterObject(unittest.TestCase): def test_signature_parameter_kinds(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,9 @@ - Issue #20595: Make getargs.c C89 compliant. +- Issue #20625: Parameter names in __annotations__ were not mangled properly. + Discovered by Jonas Wielicki, patch by Yury Selivanov. + Library ------- diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1533,8 +1533,14 @@ { if (annotation) { VISIT(c, expr, annotation); - if (PyList_Append(names, id)) + PyObject *mangled = _Py_Mangle(c->u->u_private, id); + if (!mangled) return -1; + if (PyList_Append(names, mangled) < 0) { + Py_DECREF(mangled); + return -1; + } + Py_DECREF(mangled); } return 0; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 19:24:46 2014 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 18 Feb 2014 19:24:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Make_tests_pass?= =?utf-8?q?_on_Windows=2E?= Message-ID: <3fT9TB5BD7z7LjX@mail.python.org> http://hg.python.org/cpython/rev/f81106f36656 changeset: 89257:f81106f36656 user: Guido van Rossum date: Tue Feb 18 10:24:30 2014 -0800 summary: asyncio: Make tests pass on Windows. files: Lib/asyncio/streams.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -2,12 +2,14 @@ __all__ = ['StreamReader', 'StreamWriter', 'StreamReaderProtocol', 'open_connection', 'start_server', - 'open_unix_connection', 'start_unix_server', 'IncompleteReadError', ] import socket +if hasattr(socket, 'AF_UNIX'): + __all__.extend(['open_unix_connection', 'start_unix_server']) + from . import events from . import futures from . import protocols -- Repository URL: http://hg.python.org/cpython From root at python.org Tue Feb 18 20:30:04 2014 From: root at python.org (Cron Daemon) Date: Tue, 18 Feb 2014 20:30:04 +0100 Subject: [Python-checkins] Cron /home/docs/build-devguide Message-ID: abort: error: Name or service not known From python-checkins at python.org Tue Feb 18 21:37:08 2014 From: python-checkins at python.org (ethan.furman) Date: Tue, 18 Feb 2014 21:37:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_issue20653=3A_allow_?= =?utf-8?q?Enum_subclasses_to_override_=5F=5Freduce=5Fex=5F=5F?= Message-ID: <3fTDPw4Z18z7LlM@mail.python.org> http://hg.python.org/cpython/rev/587fd4b91120 changeset: 89258:587fd4b91120 user: Ethan Furman date: Tue Feb 18 12:37:12 2014 -0800 summary: Close issue20653: allow Enum subclasses to override __reduce_ex__ files: Lib/enum.py | 26 ++++++------ Lib/test/test_enum.py | 61 ++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/Lib/enum.py b/Lib/enum.py --- a/Lib/enum.py +++ b/Lib/enum.py @@ -116,12 +116,14 @@ enum_class._value2member_map_ = {} # check for a supported pickle protocols, and if not present sabotage - # pickling, since it won't work anyway - if member_type is not object: - methods = ('__getnewargs_ex__', '__getnewargs__', - '__reduce_ex__', '__reduce__') - if not any(map(member_type.__dict__.get, methods)): - _make_class_unpicklable(enum_class) + # pickling, since it won't work anyway. + # if new class implements its own __reduce_ex__, do not sabotage + if classdict.get('__reduce_ex__') is None: + if member_type is not object: + methods = ('__getnewargs_ex__', '__getnewargs__', + '__reduce_ex__', '__reduce__') + if not any(map(member_type.__dict__.get, methods)): + _make_class_unpicklable(enum_class) # instantiate them, checking for duplicates as we go # we instantiate first instead of checking for duplicates first in case @@ -167,7 +169,7 @@ # double check that repr and friends are not the mixin's or various # things break (such as pickle) - for name in ('__repr__', '__str__', '__format__', '__getnewargs__', '__reduce_ex__'): + for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'): class_method = getattr(enum_class, name) obj_method = getattr(member_type, name, None) enum_method = getattr(first_enum, name, None) @@ -192,8 +194,9 @@ (i.e. Color = Enum('Color', names='red green blue')). When used for the functional API: `module`, if set, will be stored in - the new class' __module__ attribute; `type`, if set, will be mixed in - as the first base class. + the new class' __module__ attribute; `qualname`, if set, will be stored + in the new class' __qualname__ attribute; `type`, if set, will be mixed + in as the first base class. Note: if `module` is not set this routine will attempt to discover the calling module by walking the frame stack; if this is unsuccessful @@ -465,14 +468,11 @@ val = self.value return cls.__format__(val, format_spec) - def __getnewargs__(self): - return (self._value_, ) - def __hash__(self): return hash(self._name_) def __reduce_ex__(self, proto): - return self.__class__, self.__getnewargs__() + return self.__class__, (self._value_, ) # DynamicClassAttribute is used to provide access to the `name` and # `value` properties of enum members while keeping some measure of diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -956,6 +956,7 @@ test_pickle_dump_load(self.assertEqual, NI5, 5) self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertIs, NEI.y) + test_pickle_dump_load(self.assertIs, NEI) def test_subclasses_with_getnewargs_ex(self): class NamedInt(int): @@ -1012,6 +1013,7 @@ test_pickle_dump_load(self.assertEqual, NI5, 5, protocol=(4, 4)) self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertIs, NEI.y, protocol=(4, 4)) + test_pickle_dump_load(self.assertIs, NEI) def test_subclasses_with_reduce(self): class NamedInt(int): @@ -1068,6 +1070,7 @@ test_pickle_dump_load(self.assertEqual, NI5, 5) self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertIs, NEI.y) + test_pickle_dump_load(self.assertIs, NEI) def test_subclasses_with_reduce_ex(self): class NamedInt(int): @@ -1124,8 +1127,9 @@ test_pickle_dump_load(self.assertEqual, NI5, 5) self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertIs, NEI.y) + test_pickle_dump_load(self.assertIs, NEI) - def test_subclasses_without_getnewargs(self): + def test_subclasses_without_direct_pickle_support(self): class NamedInt(int): __qualname__ = 'NamedInt' def __new__(cls, *args): @@ -1178,6 +1182,61 @@ test_pickle_exception(self.assertRaises, TypeError, NEI.x) test_pickle_exception(self.assertRaises, PicklingError, NEI) + def test_subclasses_without_direct_pickle_support_using_name(self): + class NamedInt(int): + __qualname__ = 'NamedInt' + def __new__(cls, *args): + _args = args + name, *args = args + if len(args) == 0: + raise TypeError("name and value must be specified") + self = int.__new__(cls, *args) + self._intname = name + self._args = _args + return self + @property + def __name__(self): + return self._intname + def __repr__(self): + # repr() is updated to include the name and type info + return "{}({!r}, {})".format(type(self).__name__, + self.__name__, + int.__repr__(self)) + def __str__(self): + # str() is unchanged, even if it relies on the repr() fallback + base = int + base_str = base.__str__ + if base_str.__objclass__ is object: + return base.__repr__(self) + return base_str(self) + # for simplicity, we only define one operator that + # propagates expressions + def __add__(self, other): + temp = int(self) + int( other) + if isinstance(self, NamedInt) and isinstance(other, NamedInt): + return NamedInt( + '({0} + {1})'.format(self.__name__, other.__name__), + temp ) + else: + return temp + + class NEI(NamedInt, Enum): + __qualname__ = 'NEI' + x = ('the-x', 1) + y = ('the-y', 2) + def __reduce_ex__(self, proto): + return getattr, (self.__class__, self._name_) + + self.assertIs(NEI.__new__, Enum.__new__) + self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") + globals()['NamedInt'] = NamedInt + globals()['NEI'] = NEI + NI5 = NamedInt('test', 5) + self.assertEqual(NI5, 5) + self.assertEqual(NEI.y.value, 2) + test_pickle_dump_load(self.assertIs, NEI.y) + test_pickle_dump_load(self.assertIs, NEI) + def test_tuple_subclass(self): class SomeTuple(tuple, Enum): __qualname__ = 'SomeTuple' # needed for pickle protocol 4 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 22:08:14 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 22:08:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE5NjEy?= =?utf-8?q?=3A_On_Windows=2C_subprocess=2EPopen=2Ecommunicate=28=29_now_ig?= =?utf-8?q?nores?= Message-ID: <3fTF5p6LySz7Lnh@mail.python.org> http://hg.python.org/cpython/rev/83013a7be836 changeset: 89259:83013a7be836 branch: 3.3 parent: 89254:d610a2740b5f user: Victor Stinner date: Tue Feb 18 22:00:53 2014 +0100 summary: Issue #19612: On Windows, subprocess.Popen.communicate() now ignores OSError(22, 'Invalid argument') when writing input data into stdin, whereas the process already exited. files: Lib/subprocess.py | 10 +++++++++- Misc/NEWS | 6 +++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1193,7 +1193,15 @@ try: self.stdin.write(input) except IOError as e: - if e.errno != errno.EPIPE: + if e.errno == errno.EPIPE: + # ignore pipe full error + pass + elif (e.errno == errno.EINVAL + and self.poll() is not None): + # Issue #19612: stdin.write() fails with EINVAL + # if the process already exited before the write + pass + else: raise self.stdin.close() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -20,6 +20,10 @@ Library ------- +- Issue #19612: On Windows, subprocess.Popen.communicate() now ignores + OSError(22, 'Invalid argument') when writing input data into stdin, whereas + the process already exited. + - Issue #6815: os.path.expandvars() now supports non-ASCII environment variables names and values. @@ -27,7 +31,7 @@ Based on patch by Stephen Tu. - Issue #8478: Untokenizer.compat processes first token from iterator input. - Patch based on lines from Georg Brandl, Eric Snow, and Gareth Rees. + Patch based on lines from Georg Brandl, Eric Snow, and Gareth Rees. - Issue #20594: Avoid name clash with the libc function posix_close. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 22:08:16 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 22:08:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_=28Merge_3=2E3=29_Issue_=2319612=3A_On_Windows=2C_subpro?= =?utf-8?q?cess=2EPopen=2Ecommunicate=28=29_now?= Message-ID: <3fTF5r2mXHz7Lnr@mail.python.org> http://hg.python.org/cpython/rev/423cb79640eb changeset: 89260:423cb79640eb parent: 89258:587fd4b91120 parent: 89259:83013a7be836 user: Victor Stinner date: Tue Feb 18 22:06:35 2014 +0100 summary: (Merge 3.3) Issue #19612: On Windows, subprocess.Popen.communicate() now ignores OSError(22, 'Invalid argument') when writing input data into stdin, whereas the process already exited. files: Lib/subprocess.py | 10 +++++++++- Misc/NEWS | 4 ++++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1186,7 +1186,15 @@ try: self.stdin.write(input) except OSError as e: - if e.errno != errno.EPIPE: + if e.errno == errno.EPIPE: + # communicate() should ignore pipe full error + pass + elif (e.errno == errno.EINVAL + and self.poll() is not None): + # Issue #19612: stdin.write() fails with EINVAL + # if the process already exited before the write + pass + else: raise self.stdin.close() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,10 @@ Library ------- +- Issue #19612: On Windows, subprocess.Popen.communicate() now ignores + OSError(22, 'Invalid argument') when writing input data into stdin, whereas + the process already exited. + - Issue #20320: select.select() and select.kqueue.control() now round the timeout aways from zero, instead of rounding towards zero. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 18 22:08:17 2014 From: python-checkins at python.org (victor.stinner) Date: Tue, 18 Feb 2014 22:08:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320625=3A_Fix_comp?= =?utf-8?q?ilation_issue?= Message-ID: <3fTF5s5vCGz7LnB@mail.python.org> http://hg.python.org/cpython/rev/5202aca8a673 changeset: 89261:5202aca8a673 user: Victor Stinner date: Tue Feb 18 22:07:56 2014 +0100 summary: Issue #20625: Fix compilation issue files: Python/compile.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -1532,8 +1532,9 @@ expr_ty annotation, PyObject *names) { if (annotation) { + PyObject *mangled; VISIT(c, expr, annotation); - PyObject *mangled = _Py_Mangle(c->u->u_private, id); + mangled = _Py_Mangle(c->u->u_private, id); if (!mangled) return -1; if (PyList_Append(names, mangled) < 0) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 00:02:53 2014 From: python-checkins at python.org (yury.selivanov) Date: Wed, 19 Feb 2014 00:02:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_New_error_handl?= =?utf-8?q?ing_API=2E_Issue_=2320681=2E?= Message-ID: <3fTHf54q4tz7LnN@mail.python.org> http://hg.python.org/cpython/rev/7c1de1ebb894 changeset: 89262:7c1de1ebb894 user: Yury Selivanov date: Tue Feb 18 18:02:19 2014 -0500 summary: asyncio: New error handling API. Issue #20681. files: Lib/asyncio/base_events.py | 96 ++++- Lib/asyncio/events.py | 31 +- Lib/asyncio/futures.py | 22 +- Lib/asyncio/proactor_events.py | 33 +- Lib/asyncio/selector_events.py | 35 +- Lib/asyncio/test_utils.py | 18 +- Lib/asyncio/unix_events.py | 26 +- Lib/asyncio/windows_events.py | 8 +- Lib/test/test_asyncio/test_base_events.py | 194 +++++++++- Lib/test/test_asyncio/test_events.py | 44 +- Lib/test/test_asyncio/test_futures.py | 12 +- Lib/test/test_asyncio/test_proactor_events.py | 8 +- Lib/test/test_asyncio/test_selector_events.py | 20 +- Lib/test/test_asyncio/test_unix_events.py | 39 +- Misc/NEWS | 4 + 15 files changed, 491 insertions(+), 99 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -122,6 +122,7 @@ self._internal_fds = 0 self._running = False self._clock_resolution = time.get_clock_info('monotonic').resolution + self._exception_handler = None def _make_socket_transport(self, sock, protocol, waiter=None, *, extra=None, server=None): @@ -254,7 +255,7 @@ """Like call_later(), but uses an absolute time.""" if tasks.iscoroutinefunction(callback): raise TypeError("coroutines cannot be used with call_at()") - timer = events.TimerHandle(when, callback, args) + timer = events.TimerHandle(when, callback, args, self) heapq.heappush(self._scheduled, timer) return timer @@ -270,7 +271,7 @@ """ if tasks.iscoroutinefunction(callback): raise TypeError("coroutines cannot be used with call_soon()") - handle = events.Handle(callback, args) + handle = events.Handle(callback, args, self) self._ready.append(handle) return handle @@ -625,6 +626,97 @@ protocol, popen_args, False, stdin, stdout, stderr, bufsize, **kwargs) return transport, protocol + def set_exception_handler(self, handler): + """Set handler as the new event loop exception handler. + + If handler is None, the default exception handler will + be set. + + If handler is a callable object, it should have a + matching signature to '(loop, context)', where 'loop' + will be a reference to the active event loop, 'context' + will be a dict object (see `call_exception_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)) + self._exception_handler = handler + + def default_exception_handler(self, context): + """Default exception handler. + + This is called when an exception occurs and no exception + handler is set, and can be called by a custom exception + handler that wants to defer to the default behavior. + + context parameter has the same meaning as in + `call_exception_handler()`. + """ + message = context.get('message') + if not message: + message = 'Unhandled exception in event loop' + + exception = context.get('exception') + if exception is not None: + exc_info = (type(exception), exception, exception.__traceback__) + else: + exc_info = False + + log_lines = [message] + for key in sorted(context): + if key in {'message', 'exception'}: + continue + log_lines.append('{}: {!r}'.format(key, context[key])) + + logger.error('\n'.join(log_lines), exc_info=exc_info) + + def call_exception_handler(self, context): + """Call the current event loop exception handler. + + context is a dict object containing the following keys + (new keys maybe introduced later): + - 'message': Error message; + - 'exception' (optional): Exception object; + - 'future' (optional): Future instance; + - 'handle' (optional): Handle instance; + - 'protocol' (optional): Protocol instance; + - 'transport' (optional): Transport instance; + - 'socket' (optional): Socket instance. + + Note: this method should not be overloaded in subclassed + event loops. For any custom exception handling, use + `set_exception_handler()` method. + """ + if self._exception_handler is None: + try: + self.default_exception_handler(context) + except Exception: + # Second protection layer for unexpected errors + # in the default implementation, as well as for subclassed + # event loops with overloaded "default_exception_handler". + logger.error('Exception in default exception handler', + exc_info=True) + else: + try: + self._exception_handler(self, context) + except Exception as exc: + # Exception in the user set custom exception handler. + try: + # Let's try default handler. + self.default_exception_handler({ + 'message': 'Unhandled error in exception handler', + 'exception': exc, + 'context': context, + }) + except Exception: + # Guard 'default_exception_handler' in case it's + # overloaded. + logger.error('Exception in default exception handler ' + 'while handling an unexpected error ' + 'in custom exception handler', + exc_info=True) + def _add_callback(self, handle): """Add a Handle to ready or scheduled.""" assert isinstance(handle, events.Handle), 'A Handle is required here' diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -19,10 +19,11 @@ class Handle: """Object returned by callback registration methods.""" - __slots__ = ['_callback', '_args', '_cancelled'] + __slots__ = ['_callback', '_args', '_cancelled', '_loop'] - def __init__(self, callback, args): + def __init__(self, callback, args, loop): assert not isinstance(callback, Handle), 'A Handle is not a callback' + self._loop = loop self._callback = callback self._args = args self._cancelled = False @@ -39,9 +40,14 @@ def _run(self): try: self._callback(*self._args) - except Exception: - logger.exception('Exception in callback %s %r', - self._callback, self._args) + except Exception as exc: + msg = 'Exception in callback {}{!r}'.format(self._callback, + self._args) + self._loop.call_exception_handler({ + 'message': msg, + 'exception': exc, + 'handle': self, + }) self = None # Needed to break cycles when an exception occurs. @@ -50,9 +56,9 @@ __slots__ = ['_when'] - def __init__(self, when, callback, args): + def __init__(self, when, callback, args, loop): assert when is not None - super().__init__(callback, args) + super().__init__(callback, args, loop) self._when = when @@ -328,6 +334,17 @@ def remove_signal_handler(self, sig): raise NotImplementedError + # Error handlers. + + def set_exception_handler(self, handler): + raise NotImplementedError + + def default_exception_handler(self, context): + raise NotImplementedError + + def call_exception_handler(self, context): + raise NotImplementedError + class AbstractEventLoopPolicy: """Abstract policy for accessing the event loop.""" diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -83,9 +83,10 @@ in a discussion about closing files when they are collected. """ - __slots__ = ['exc', 'tb'] + __slots__ = ['exc', 'tb', 'loop'] - def __init__(self, exc): + def __init__(self, exc, loop): + self.loop = loop self.exc = exc self.tb = None @@ -102,8 +103,11 @@ def __del__(self): if self.tb: - logger.error('Future/Task exception was never retrieved:\n%s', - ''.join(self.tb)) + msg = 'Future/Task exception was never retrieved:\n{tb}' + context = { + 'message': msg.format(tb=''.join(self.tb)), + } + self.loop.call_exception_handler(context) class Future: @@ -173,8 +177,12 @@ # has consumed the exception return exc = self._exception - logger.error('Future/Task exception was never retrieved:', - exc_info=(exc.__class__, exc, exc.__traceback__)) + context = { + 'message': 'Future/Task exception was never retrieved', + 'exception': exc, + 'future': self, + } + self._loop.call_exception_handler(context) def cancel(self): """Cancel the future and schedule callbacks. @@ -309,7 +317,7 @@ if _PY34: self._log_traceback = True else: - self._tb_logger = _TracebackLogger(exception) + self._tb_logger = _TracebackLogger(exception, self._loop) # Arrange for the logger to be activated after all callbacks # have had a chance to call result() or exception(). self._loop.call_soon(self._tb_logger.activate) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -56,7 +56,12 @@ def _fatal_error(self, exc): if not isinstance(exc, (BrokenPipeError, ConnectionResetError)): - logger.exception('Fatal error for %s', self) + self._loop.call_exception_handler({ + 'message': 'Fatal transport error', + 'exception': exc, + 'transport': self, + 'protocol': self._protocol, + }) self._force_close(exc) def _force_close(self, exc): @@ -103,8 +108,13 @@ self._protocol_paused = True try: self._protocol.pause_writing() - except Exception: - logger.exception('pause_writing() failed') + except Exception as exc: + self._loop.call_exception_handler({ + 'message': 'protocol.pause_writing() failed', + 'exception': exc, + 'transport': self, + 'protocol': self._protocol, + }) def _maybe_resume_protocol(self): if (self._protocol_paused and @@ -112,8 +122,13 @@ self._protocol_paused = False try: self._protocol.resume_writing() - except Exception: - logger.exception('resume_writing() failed') + except Exception as exc: + self._loop.call_exception_handler({ + 'message': 'protocol.resume_writing() failed', + 'exception': exc, + 'transport': self, + 'protocol': self._protocol, + }) def set_write_buffer_limits(self, high=None, low=None): if high is None: @@ -465,9 +480,13 @@ conn, protocol, extra={'peername': addr}, server=server) f = self._proactor.accept(sock) - except OSError: + except OSError as exc: if sock.fileno() != -1: - logger.exception('Accept failed') + self.call_exception_handler({ + 'message': 'Accept failed', + 'exception': exc, + 'socket': sock, + }) sock.close() except futures.CancelledError: sock.close() diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -112,7 +112,11 @@ # Some platforms (e.g. Linux keep reporting the FD as # ready, so we remove the read handler temporarily. # We'll try again in a while. - logger.exception('Accept out of system resource (%s)', exc) + self.call_exception_handler({ + 'message': 'socket.accept() out of system resource', + 'exception': exc, + 'socket': sock, + }) self.remove_reader(sock.fileno()) self.call_later(constants.ACCEPT_RETRY_DELAY, self._start_serving, @@ -132,7 +136,7 @@ def add_reader(self, fd, callback, *args): """Add a reader callback.""" - handle = events.Handle(callback, args) + handle = events.Handle(callback, args, self) try: key = self._selector.get_key(fd) except KeyError: @@ -167,7 +171,7 @@ def add_writer(self, fd, callback, *args): """Add a writer callback..""" - handle = events.Handle(callback, args) + handle = events.Handle(callback, args, self) try: key = self._selector.get_key(fd) except KeyError: @@ -364,8 +368,13 @@ self._protocol_paused = True try: self._protocol.pause_writing() - except Exception: - logger.exception('pause_writing() failed') + except Exception as exc: + self._loop.call_exception_handler({ + 'message': 'protocol.pause_writing() failed', + 'exception': exc, + 'transport': self, + 'protocol': self._protocol, + }) def _maybe_resume_protocol(self): if (self._protocol_paused and @@ -373,8 +382,13 @@ self._protocol_paused = False try: self._protocol.resume_writing() - except Exception: - logger.exception('resume_writing() failed') + except Exception as exc: + self._loop.call_exception_handler({ + 'message': 'protocol.resume_writing() failed', + 'exception': exc, + 'transport': self, + 'protocol': self._protocol, + }) def set_write_buffer_limits(self, high=None, low=None): if high is None: @@ -435,7 +449,12 @@ def _fatal_error(self, exc): # Should be called from exception handler only. if not isinstance(exc, (BrokenPipeError, ConnectionResetError)): - logger.exception('Fatal error for %s', self) + self._loop.call_exception_handler({ + 'message': 'Fatal transport error', + 'exception': exc, + 'transport': self, + 'protocol': self._protocol, + }) self._force_close(exc) def _force_close(self, exc): diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -4,6 +4,7 @@ import contextlib import io import os +import re import socket import socketserver import sys @@ -301,7 +302,7 @@ raise AssertionError("Time generator is not finished") def add_reader(self, fd, callback, *args): - self.readers[fd] = events.Handle(callback, args) + self.readers[fd] = events.Handle(callback, args, self) def remove_reader(self, fd): self.remove_reader_count[fd] += 1 @@ -320,7 +321,7 @@ handle._args, args) def add_writer(self, fd, callback, *args): - self.writers[fd] = events.Handle(callback, args) + self.writers[fd] = events.Handle(callback, args, self) def remove_writer(self, fd): self.remove_writer_count[fd] += 1 @@ -362,3 +363,16 @@ def MockCallback(**kwargs): return unittest.mock.Mock(spec=['__call__'], **kwargs) + + +class MockPattern(str): + """A regex based str with a fuzzy __eq__. + + Use this helper with 'mock.assert_called_with', or anywhere + where a regexp comparison between strings is needed. + + For instance: + mock_call.assert_called_with(MockPattern('spam.*ham')) + """ + def __eq__(self, other): + return bool(re.search(str(self), other, re.S)) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -65,7 +65,7 @@ except ValueError as exc: raise RuntimeError(str(exc)) - handle = events.Handle(callback, args) + handle = events.Handle(callback, args, self) self._signal_handlers[sig] = handle try: @@ -294,7 +294,12 @@ def _fatal_error(self, exc): # should be called by exception handler only if not (isinstance(exc, OSError) and exc.errno == errno.EIO): - logger.exception('Fatal error for %s', self) + self._loop.call_exception_handler({ + 'message': 'Fatal transport error', + 'exception': exc, + 'transport': self, + 'protocol': self._protocol, + }) self._close(exc) def _close(self, exc): @@ -441,7 +446,12 @@ def _fatal_error(self, exc): # should be called by exception handler only if not isinstance(exc, (BrokenPipeError, ConnectionResetError)): - logger.exception('Fatal error for %s', self) + self._loop.call_exception_handler({ + 'message': 'Fatal transport error', + 'exception': exc, + 'transport': self, + 'protocol': self._protocol, + }) self._close(exc) def _close(self, exc=None): @@ -582,8 +592,14 @@ def _sig_chld(self): try: self._do_waitpid_all() - except Exception: - logger.exception('Unknown exception in SIGCHLD handler') + except Exception as exc: + # self._loop should always be available here + # as '_sig_chld' is added as a signal handler + # in 'attach_loop' + self._loop.call_exception_handler({ + 'message': 'Unknown exception in SIGCHLD handler', + 'exception': exc, + }) def _compute_returncode(self, status): if os.WIFSIGNALED(status): diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -156,9 +156,13 @@ if pipe is None: return f = self._proactor.accept_pipe(pipe) - except OSError: + except OSError as exc: if pipe and pipe.fileno() != -1: - logger.exception('Pipe accept failed') + self.call_exception_handler({ + 'message': 'Pipe accept failed', + 'exception': exc, + 'pipe': pipe, + }) pipe.close() except futures.CancelledError: if pipe: diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -15,6 +15,10 @@ from asyncio import test_utils +MOCK_ANY = unittest.mock.ANY +PY34 = sys.version_info >= (3, 4) + + class BaseEventLoopTests(unittest.TestCase): def setUp(self): @@ -49,20 +53,21 @@ self.assertRaises(NotImplementedError, next, iter(gen)) def test__add_callback_handle(self): - h = asyncio.Handle(lambda: False, ()) + h = asyncio.Handle(lambda: False, (), self.loop) self.loop._add_callback(h) self.assertFalse(self.loop._scheduled) self.assertIn(h, self.loop._ready) def test__add_callback_timer(self): - h = asyncio.TimerHandle(time.monotonic()+10, lambda: False, ()) + h = asyncio.TimerHandle(time.monotonic()+10, lambda: False, (), + self.loop) self.loop._add_callback(h) self.assertIn(h, self.loop._scheduled) def test__add_callback_cancelled_handle(self): - h = asyncio.Handle(lambda: False, ()) + h = asyncio.Handle(lambda: False, (), self.loop) h.cancel() self.loop._add_callback(h) @@ -137,15 +142,15 @@ self.assertRaises( AssertionError, self.loop.run_in_executor, - None, asyncio.Handle(cb, ()), ('',)) + None, asyncio.Handle(cb, (), self.loop), ('',)) self.assertRaises( AssertionError, self.loop.run_in_executor, - None, asyncio.TimerHandle(10, cb, ())) + None, asyncio.TimerHandle(10, cb, (), self.loop)) def test_run_once_in_executor_cancelled(self): def cb(): pass - h = asyncio.Handle(cb, ()) + h = asyncio.Handle(cb, (), self.loop) h.cancel() f = self.loop.run_in_executor(None, h) @@ -156,7 +161,7 @@ def test_run_once_in_executor_plain(self): def cb(): pass - h = asyncio.Handle(cb, ()) + h = asyncio.Handle(cb, (), self.loop) f = asyncio.Future(loop=self.loop) executor = unittest.mock.Mock() executor.submit.return_value = f @@ -175,8 +180,10 @@ f.cancel() # Don't complain about abandoned Future. def test__run_once(self): - h1 = asyncio.TimerHandle(time.monotonic() + 5.0, lambda: True, ()) - h2 = asyncio.TimerHandle(time.monotonic() + 10.0, lambda: True, ()) + h1 = asyncio.TimerHandle(time.monotonic() + 5.0, lambda: True, (), + self.loop) + h2 = asyncio.TimerHandle(time.monotonic() + 10.0, lambda: True, (), + self.loop) h1.cancel() @@ -205,14 +212,15 @@ m_time.monotonic = monotonic self.loop._scheduled.append( - asyncio.TimerHandle(11.0, lambda: True, ())) + asyncio.TimerHandle(11.0, lambda: True, (), self.loop)) self.loop._process_events = unittest.mock.Mock() self.loop._run_once() self.assertEqual(logging.INFO, m_logger.log.call_args[0][0]) idx = -1 data = [10.0, 10.0, 10.3, 13.0] - self.loop._scheduled = [asyncio.TimerHandle(11.0, lambda: True, ())] + self.loop._scheduled = [asyncio.TimerHandle(11.0, lambda: True, (), + self.loop)] self.loop._run_once() self.assertEqual(logging.DEBUG, m_logger.log.call_args[0][0]) @@ -225,7 +233,8 @@ processed = True handle = loop.call_soon(lambda: True) - h = asyncio.TimerHandle(time.monotonic() - 1, cb, (self.loop,)) + h = asyncio.TimerHandle(time.monotonic() - 1, cb, (self.loop,), + self.loop) self.loop._process_events = unittest.mock.Mock() self.loop._scheduled.append(h) @@ -287,6 +296,163 @@ self.loop.run_until_complete, self.loop.subprocess_shell, asyncio.SubprocessProtocol, 'exit 0', bufsize=4096) + def test_default_exc_handler_callback(self): + self.loop._process_events = unittest.mock.Mock() + + def zero_error(fut): + fut.set_result(True) + 1/0 + + # Test call_soon (events.Handle) + with unittest.mock.patch('asyncio.base_events.logger') as log: + fut = asyncio.Future(loop=self.loop) + self.loop.call_soon(zero_error, fut) + fut.add_done_callback(lambda fut: self.loop.stop()) + self.loop.run_forever() + log.error.assert_called_with( + test_utils.MockPattern('Exception in callback.*zero'), + exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) + + # Test call_later (events.TimerHandle) + with unittest.mock.patch('asyncio.base_events.logger') as log: + fut = asyncio.Future(loop=self.loop) + self.loop.call_later(0.01, zero_error, fut) + fut.add_done_callback(lambda fut: self.loop.stop()) + self.loop.run_forever() + log.error.assert_called_with( + test_utils.MockPattern('Exception in callback.*zero'), + exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) + + def test_default_exc_handler_coro(self): + self.loop._process_events = unittest.mock.Mock() + + @asyncio.coroutine + def zero_error_coro(): + yield from asyncio.sleep(0.01, loop=self.loop) + 1/0 + + # Test Future.__del__ + with unittest.mock.patch('asyncio.base_events.logger') as log: + fut = asyncio.async(zero_error_coro(), loop=self.loop) + fut.add_done_callback(lambda *args: self.loop.stop()) + self.loop.run_forever() + fut = None # Trigger Future.__del__ or futures._TracebackLogger + if PY34: + # Future.__del__ in Python 3.4 logs error with + # an actual exception context + log.error.assert_called_with( + test_utils.MockPattern('.*exception was never retrieved'), + exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) + else: + # futures._TracebackLogger logs only textual traceback + log.error.assert_called_with( + test_utils.MockPattern( + '.*exception was never retrieved.*ZeroDiv'), + exc_info=False) + + def test_set_exc_handler_invalid(self): + with self.assertRaisesRegex(TypeError, 'A callable object or None'): + self.loop.set_exception_handler('spam') + + def test_set_exc_handler_custom(self): + def zero_error(): + 1/0 + + def run_loop(): + self.loop.call_soon(zero_error) + self.loop._run_once() + + self.loop._process_events = unittest.mock.Mock() + + mock_handler = unittest.mock.Mock() + self.loop.set_exception_handler(mock_handler) + run_loop() + mock_handler.assert_called_with(self.loop, { + 'exception': MOCK_ANY, + 'message': test_utils.MockPattern( + 'Exception in callback.*zero_error'), + 'handle': MOCK_ANY, + }) + mock_handler.reset_mock() + + self.loop.set_exception_handler(None) + with unittest.mock.patch('asyncio.base_events.logger') as log: + run_loop() + log.error.assert_called_with( + test_utils.MockPattern( + 'Exception in callback.*zero'), + exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) + + assert not mock_handler.called + + def test_set_exc_handler_broken(self): + def run_loop(): + def zero_error(): + 1/0 + self.loop.call_soon(zero_error) + self.loop._run_once() + + def handler(loop, context): + raise AttributeError('spam') + + self.loop._process_events = unittest.mock.Mock() + + self.loop.set_exception_handler(handler) + + with unittest.mock.patch('asyncio.base_events.logger') as log: + run_loop() + log.error.assert_called_with( + test_utils.MockPattern( + 'Unhandled error in exception handler'), + exc_info=(AttributeError, MOCK_ANY, MOCK_ANY)) + + def test_default_exc_handler_broken(self): + _context = None + + class Loop(base_events.BaseEventLoop): + + _selector = unittest.mock.Mock() + _process_events = unittest.mock.Mock() + + def default_exception_handler(self, context): + nonlocal _context + _context = context + # Simulates custom buggy "default_exception_handler" + raise ValueError('spam') + + loop = Loop() + asyncio.set_event_loop(loop) + + def run_loop(): + def zero_error(): + 1/0 + loop.call_soon(zero_error) + loop._run_once() + + with unittest.mock.patch('asyncio.base_events.logger') as log: + run_loop() + log.error.assert_called_with( + 'Exception in default exception handler', + exc_info=True) + + def custom_handler(loop, context): + raise ValueError('ham') + + _context = None + loop.set_exception_handler(custom_handler) + with unittest.mock.patch('asyncio.base_events.logger') as log: + run_loop() + log.error.assert_called_with( + test_utils.MockPattern('Exception in default exception.*' + 'while handling.*in custom'), + exc_info=True) + + # Check that original context was passed to default + # exception handler. + self.assertIn('context', _context) + self.assertIs(type(_context['context']['exception']), + ZeroDivisionError) + class MyProto(asyncio.Protocol): done = None @@ -716,7 +882,7 @@ self.loop._accept_connection(MyProto, sock) self.assertFalse(sock.close.called) - @unittest.mock.patch('asyncio.selector_events.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_accept_connection_exception(self, m_log): sock = unittest.mock.Mock() sock.fileno.return_value = 10 @@ -725,7 +891,7 @@ self.loop.call_later = unittest.mock.Mock() self.loop._accept_connection(MyProto, sock) - self.assertTrue(m_log.exception.called) + 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, diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1788,7 +1788,7 @@ return args args = () - h = asyncio.Handle(callback, args) + h = asyncio.Handle(callback, args, unittest.mock.Mock()) self.assertIs(h._callback, callback) self.assertIs(h._args, args) self.assertFalse(h._cancelled) @@ -1808,28 +1808,37 @@ '.callback')) self.assertTrue(r.endswith('())'), r) - def test_handle(self): + def test_handle_from_handle(self): def callback(*args): return args - h1 = asyncio.Handle(callback, ()) + m_loop = object() + h1 = asyncio.Handle(callback, (), loop=m_loop) self.assertRaises( - AssertionError, asyncio.Handle, h1, ()) + AssertionError, asyncio.Handle, h1, (), m_loop) - @unittest.mock.patch('asyncio.events.logger') - def test_callback_with_exception(self, log): + def test_callback_with_exception(self): def callback(): raise ValueError() - h = asyncio.Handle(callback, ()) + m_loop = unittest.mock.Mock() + m_loop.call_exception_handler = unittest.mock.Mock() + + h = asyncio.Handle(callback, (), m_loop) h._run() - self.assertTrue(log.exception.called) + + m_loop.call_exception_handler.assert_called_with({ + 'message': test_utils.MockPattern('Exception in callback.*'), + 'exception': unittest.mock.ANY, + 'handle': h + }) class TimerTests(unittest.TestCase): def test_hash(self): when = time.monotonic() - h = asyncio.TimerHandle(when, lambda: False, ()) + h = asyncio.TimerHandle(when, lambda: False, (), + unittest.mock.Mock()) self.assertEqual(hash(h), hash(when)) def test_timer(self): @@ -1838,7 +1847,7 @@ args = () when = time.monotonic() - h = asyncio.TimerHandle(when, callback, args) + h = asyncio.TimerHandle(when, callback, args, unittest.mock.Mock()) self.assertIs(h._callback, callback) self.assertIs(h._args, args) self.assertFalse(h._cancelled) @@ -1853,16 +1862,19 @@ self.assertTrue(r.endswith('())'), r) self.assertRaises(AssertionError, - asyncio.TimerHandle, None, callback, args) + asyncio.TimerHandle, None, callback, args, + unittest.mock.Mock()) def test_timer_comparison(self): + loop = unittest.mock.Mock() + def callback(*args): return args when = time.monotonic() - h1 = asyncio.TimerHandle(when, callback, ()) - h2 = asyncio.TimerHandle(when, callback, ()) + h1 = asyncio.TimerHandle(when, callback, (), loop) + h2 = asyncio.TimerHandle(when, callback, (), loop) # TODO: Use assertLess etc. self.assertFalse(h1 < h2) self.assertFalse(h2 < h1) @@ -1878,8 +1890,8 @@ h2.cancel() self.assertFalse(h1 == h2) - h1 = asyncio.TimerHandle(when, callback, ()) - h2 = asyncio.TimerHandle(when + 10.0, callback, ()) + h1 = asyncio.TimerHandle(when, callback, (), loop) + h2 = asyncio.TimerHandle(when + 10.0, callback, (), loop) self.assertTrue(h1 < h2) self.assertFalse(h2 < h1) self.assertTrue(h1 <= h2) @@ -1891,7 +1903,7 @@ self.assertFalse(h1 == h2) self.assertTrue(h1 != h2) - h3 = asyncio.Handle(callback, ()) + h3 = asyncio.Handle(callback, (), loop) self.assertIs(NotImplemented, h1.__eq__(h3)) self.assertIs(NotImplemented, h1.__ne__(h3)) diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -174,20 +174,20 @@ self.assertRaises(AssertionError, test) fut.cancel() - @unittest.mock.patch('asyncio.futures.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_tb_logger_abandoned(self, m_log): fut = asyncio.Future(loop=self.loop) del fut self.assertFalse(m_log.error.called) - @unittest.mock.patch('asyncio.futures.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_tb_logger_result_unretrieved(self, m_log): fut = asyncio.Future(loop=self.loop) fut.set_result(42) del fut self.assertFalse(m_log.error.called) - @unittest.mock.patch('asyncio.futures.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_tb_logger_result_retrieved(self, m_log): fut = asyncio.Future(loop=self.loop) fut.set_result(42) @@ -195,7 +195,7 @@ del fut self.assertFalse(m_log.error.called) - @unittest.mock.patch('asyncio.futures.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_tb_logger_exception_unretrieved(self, m_log): fut = asyncio.Future(loop=self.loop) fut.set_exception(RuntimeError('boom')) @@ -203,7 +203,7 @@ test_utils.run_briefly(self.loop) self.assertTrue(m_log.error.called) - @unittest.mock.patch('asyncio.futures.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_tb_logger_exception_retrieved(self, m_log): fut = asyncio.Future(loop=self.loop) fut.set_exception(RuntimeError('boom')) @@ -211,7 +211,7 @@ del fut self.assertFalse(m_log.error.called) - @unittest.mock.patch('asyncio.futures.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_tb_logger_exception_result_retrieved(self, m_log): fut = asyncio.Future(loop=self.loop) fut.set_exception(RuntimeError('boom')) diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -207,13 +207,13 @@ test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.connection_lost.called) - @unittest.mock.patch('asyncio.proactor_events.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_fatal_error(self, m_logging): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._force_close = unittest.mock.Mock() tr._fatal_error(None) self.assertTrue(tr._force_close.called) - self.assertTrue(m_logging.exception.called) + self.assertTrue(m_logging.error.called) def test_force_close(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) @@ -432,7 +432,7 @@ def test_process_events(self): self.loop._process_events([]) - @unittest.mock.patch('asyncio.proactor_events.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_create_server(self, m_log): pf = unittest.mock.Mock() call_soon = self.loop.call_soon = unittest.mock.Mock() @@ -458,7 +458,7 @@ fut.result.side_effect = OSError() loop(fut) self.assertTrue(self.sock.close.called) - self.assertTrue(m_log.exception.called) + self.assertTrue(m_log.error.called) def test_create_server_cancel(self): pf = unittest.mock.Mock() diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -23,6 +23,9 @@ from asyncio.selector_events import _SelectorDatagramTransport +MOCK_ANY = unittest.mock.ANY + + class TestBaseSelectorEventLoop(BaseSelectorEventLoop): def _make_self_pipe(self): @@ -643,14 +646,18 @@ self.assertFalse(self.loop.readers) self.assertEqual(1, self.loop.remove_reader_count[7]) - @unittest.mock.patch('asyncio.log.logger.exception') + @unittest.mock.patch('asyncio.log.logger.error') def test_fatal_error(self, m_exc): exc = OSError() tr = _SelectorTransport(self.loop, self.sock, self.protocol, None) tr._force_close = unittest.mock.Mock() tr._fatal_error(exc) - m_exc.assert_called_with('Fatal error for %s', tr) + m_exc.assert_called_with( + test_utils.MockPattern( + 'Fatal transport error\nprotocol:.*\ntransport:.*'), + exc_info=(OSError, MOCK_ANY, MOCK_ANY)) + tr._force_close.assert_called_with(exc) def test_connection_lost(self): @@ -996,7 +1003,7 @@ transport._write_ready() transport._fatal_error.assert_called_with(err) - @unittest.mock.patch('asyncio.selector_events.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_write_ready_exception_and_close(self, m_log): self.sock.send.side_effect = OSError() remove_writer = self.loop.remove_writer = unittest.mock.Mock() @@ -1651,14 +1658,17 @@ self.assertFalse(transport._fatal_error.called) self.assertTrue(self.protocol.error_received.called) - @unittest.mock.patch('asyncio.log.logger.exception') + @unittest.mock.patch('asyncio.base_events.logger.error') def test_fatal_error_connected(self, m_exc): transport = _SelectorDatagramTransport( self.loop, self.sock, self.protocol, ('0.0.0.0', 1)) err = ConnectionRefusedError() transport._fatal_error(err) self.assertFalse(self.protocol.error_received.called) - m_exc.assert_called_with('Fatal error for %s', transport) + m_exc.assert_called_with( + test_utils.MockPattern( + 'Fatal transport error\nprotocol:.*\ntransport:.*'), + exc_info=(ConnectionRefusedError, MOCK_ANY, MOCK_ANY)) if __name__ == '__main__': diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -25,6 +25,9 @@ from asyncio import unix_events +MOCK_ANY = unittest.mock.ANY + + @unittest.skipUnless(signal, 'Signals are not supported') class SelectorEventLoopSignalTests(unittest.TestCase): @@ -45,7 +48,8 @@ self.loop._handle_signal(signal.NSIG + 1, ()) def test_handle_signal_cancelled_handler(self): - h = asyncio.Handle(unittest.mock.Mock(), ()) + h = asyncio.Handle(unittest.mock.Mock(), (), + loop=unittest.mock.Mock()) h.cancel() self.loop._signal_handlers[signal.NSIG + 1] = h self.loop.remove_signal_handler = unittest.mock.Mock() @@ -91,7 +95,7 @@ signal.SIGINT, lambda: True) @unittest.mock.patch('asyncio.unix_events.signal') - @unittest.mock.patch('asyncio.unix_events.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_add_signal_handler_install_error2(self, m_logging, m_signal): m_signal.NSIG = signal.NSIG @@ -108,7 +112,7 @@ self.assertEqual(1, m_signal.set_wakeup_fd.call_count) @unittest.mock.patch('asyncio.unix_events.signal') - @unittest.mock.patch('asyncio.unix_events.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_add_signal_handler_install_error3(self, m_logging, m_signal): class Err(OSError): errno = errno.EINVAL @@ -153,7 +157,7 @@ m_signal.signal.call_args[0]) @unittest.mock.patch('asyncio.unix_events.signal') - @unittest.mock.patch('asyncio.unix_events.logger') + @unittest.mock.patch('asyncio.base_events.logger') def test_remove_signal_handler_cleanup_error(self, m_logging, m_signal): m_signal.NSIG = signal.NSIG self.loop.add_signal_handler(signal.SIGHUP, lambda: True) @@ -347,7 +351,7 @@ test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.data_received.called) - @unittest.mock.patch('asyncio.log.logger.exception') + @unittest.mock.patch('asyncio.log.logger.error') @unittest.mock.patch('os.read') def test__read_ready_error(self, m_read, m_logexc): tr = unix_events._UnixReadPipeTransport( @@ -359,7 +363,10 @@ m_read.assert_called_with(5, tr.max_size) tr._close.assert_called_with(err) - m_logexc.assert_called_with('Fatal error for %s', tr) + m_logexc.assert_called_with( + test_utils.MockPattern( + 'Fatal transport error\nprotocol:.*\ntransport:.*'), + exc_info=(OSError, MOCK_ANY, MOCK_ANY)) @unittest.mock.patch('os.read') def test_pause_reading(self, m_read): @@ -423,7 +430,7 @@ self.assertEqual(2, sys.getrefcount(self.protocol), pprint.pformat(gc.get_referrers(self.protocol))) self.assertIsNone(tr._loop) - self.assertEqual(2, sys.getrefcount(self.loop), + self.assertEqual(4, sys.getrefcount(self.loop), pprint.pformat(gc.get_referrers(self.loop))) def test__call_connection_lost_with_err(self): @@ -436,10 +443,11 @@ self.pipe.close.assert_called_with() self.assertIsNone(tr._protocol) + self.assertEqual(2, sys.getrefcount(self.protocol), pprint.pformat(gc.get_referrers(self.protocol))) self.assertIsNone(tr._loop) - self.assertEqual(2, sys.getrefcount(self.loop), + self.assertEqual(4, sys.getrefcount(self.loop), pprint.pformat(gc.get_referrers(self.loop))) @@ -635,7 +643,7 @@ self.loop.assert_writer(5, tr._write_ready) self.assertEqual([b'data'], tr._buffer) - @unittest.mock.patch('asyncio.log.logger.exception') + @unittest.mock.patch('asyncio.log.logger.error') @unittest.mock.patch('os.write') def test__write_ready_err(self, m_write, m_logexc): tr = unix_events._UnixWritePipeTransport( @@ -650,7 +658,10 @@ self.assertFalse(self.loop.readers) self.assertEqual([], tr._buffer) self.assertTrue(tr._closing) - m_logexc.assert_called_with('Fatal error for %s', tr) + m_logexc.assert_called_with( + test_utils.MockPattern( + 'Fatal transport error\nprotocol:.*\ntransport:.*'), + exc_info=(OSError, MOCK_ANY, MOCK_ANY)) self.assertEqual(1, tr._conn_lost) test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(err) @@ -702,7 +713,7 @@ self.assertEqual(2, sys.getrefcount(self.protocol), pprint.pformat(gc.get_referrers(self.protocol))) self.assertIsNone(tr._loop) - self.assertEqual(2, sys.getrefcount(self.loop), + self.assertEqual(4, sys.getrefcount(self.loop), pprint.pformat(gc.get_referrers(self.loop))) def test__call_connection_lost_with_err(self): @@ -718,7 +729,7 @@ self.assertEqual(2, sys.getrefcount(self.protocol), pprint.pformat(gc.get_referrers(self.protocol))) self.assertIsNone(tr._loop) - self.assertEqual(2, sys.getrefcount(self.loop), + self.assertEqual(4, sys.getrefcount(self.loop), pprint.pformat(gc.get_referrers(self.loop))) def test_close(self): @@ -1285,10 +1296,10 @@ m.waitpid.side_effect = ValueError with unittest.mock.patch.object(log.logger, - "exception") as m_exception: + 'error') as m_error: self.assertEqual(self.watcher._sig_chld(), None) - self.assertTrue(m_exception.called) + self.assertTrue(m_error.called) @waitpid_mocks def test_sigchld_child_reaped_elsewhere(self, m): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -59,6 +59,10 @@ New APIs: loop.create_unix_connection(), loop.create_unix_server(), streams.open_unix_connection(), and streams.start_unix_server(). +- Issue #20681: Add new error handling API in asyncio. New APIs: + loop.set_exception_handler(), loop.default_exception_handler(), and + loop.call_exception_handler(). + Tests ----- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 00:42:00 2014 From: python-checkins at python.org (yury.selivanov) Date: Wed, 19 Feb 2014 00:42:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Etransports=3A_Ma?= =?utf-8?q?ke_=5FProactorBasePipeTransport_use_=5FFlowControlMixin?= Message-ID: <3fTJWD6BH6z7LjX@mail.python.org> http://hg.python.org/cpython/rev/72dba0d11235 changeset: 89263:72dba0d11235 user: Yury Selivanov date: Tue Feb 18 18:41:13 2014 -0500 summary: asyncio.transports: Make _ProactorBasePipeTransport use _FlowControlMixin files: Lib/asyncio/proactor_events.py | 55 +--------------- Lib/asyncio/selector_events.py | 73 +--------------------- Lib/asyncio/transports.py | 70 +++++++++++++++++++++ Lib/asyncio/unix_events.py | 2 +- 4 files changed, 75 insertions(+), 125 deletions(-) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -15,7 +15,8 @@ from .log import logger -class _ProactorBasePipeTransport(transports.BaseTransport): +class _ProactorBasePipeTransport(transports._FlowControlMixin, + transports.BaseTransport): """Base class for pipe and socket transports.""" def __init__(self, loop, sock, protocol, waiter=None, @@ -33,8 +34,6 @@ self._conn_lost = 0 self._closing = False # Set when close() called. self._eof_written = False - self._protocol_paused = False - self.set_write_buffer_limits() if self._server is not None: self._server.attach(self) self._loop.call_soon(self._protocol.connection_made, self) @@ -94,56 +93,6 @@ server.detach(self) self._server = None - # XXX The next four methods are nearly identical to corresponding - # ones in _SelectorTransport. Maybe refactor buffer management to - # share the implementations? (Also these are really only needed - # by _ProactorWritePipeTransport but since _buffer is defined on - # the base class I am putting it here for now.) - - def _maybe_pause_protocol(self): - size = self.get_write_buffer_size() - if size <= self._high_water: - return - if not self._protocol_paused: - self._protocol_paused = True - try: - self._protocol.pause_writing() - except Exception as exc: - self._loop.call_exception_handler({ - 'message': 'protocol.pause_writing() failed', - 'exception': exc, - 'transport': self, - 'protocol': self._protocol, - }) - - def _maybe_resume_protocol(self): - if (self._protocol_paused and - self.get_write_buffer_size() <= self._low_water): - self._protocol_paused = False - try: - self._protocol.resume_writing() - except Exception as exc: - self._loop.call_exception_handler({ - 'message': 'protocol.resume_writing() failed', - 'exception': exc, - 'transport': self, - 'protocol': self._protocol, - }) - - def set_write_buffer_limits(self, high=None, low=None): - if high is None: - if low is None: - high = 64*1024 - else: - 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)) - self._high_water = high - self._low_water = low - def get_write_buffer_size(self): size = self._pending_write if self._buffer is not None: diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -338,77 +338,8 @@ sock.close() -class _FlowControlMixin(transports.Transport): - """All the logic for (write) flow control in a mix-in base class. - - The subclass must implement get_write_buffer_size(). It must call - _maybe_pause_protocol() whenever the write buffer size increases, - and _maybe_resume_protocol() whenever it decreases. It may also - override set_write_buffer_limits() (e.g. to specify different - defaults). - - The subclass constructor must call super().__init__(extra). This - will call set_write_buffer_limits(). - - The user may call set_write_buffer_limits() and - get_write_buffer_size(), and their protocol's pause_writing() and - resume_writing() may be called. - """ - - def __init__(self, extra=None): - super().__init__(extra) - self._protocol_paused = False - self.set_write_buffer_limits() - - def _maybe_pause_protocol(self): - size = self.get_write_buffer_size() - if size <= self._high_water: - return - if not self._protocol_paused: - self._protocol_paused = True - try: - self._protocol.pause_writing() - except Exception as exc: - self._loop.call_exception_handler({ - 'message': 'protocol.pause_writing() failed', - 'exception': exc, - 'transport': self, - 'protocol': self._protocol, - }) - - def _maybe_resume_protocol(self): - if (self._protocol_paused and - self.get_write_buffer_size() <= self._low_water): - self._protocol_paused = False - try: - self._protocol.resume_writing() - except Exception as exc: - self._loop.call_exception_handler({ - 'message': 'protocol.resume_writing() failed', - 'exception': exc, - 'transport': self, - 'protocol': self._protocol, - }) - - def set_write_buffer_limits(self, high=None, low=None): - if high is None: - if low is None: - high = 64*1024 - else: - 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)) - self._high_water = high - self._low_water = low - - def get_write_buffer_size(self): - raise NotImplementedError - - -class _SelectorTransport(_FlowControlMixin, transports.Transport): +class _SelectorTransport(transports._FlowControlMixin, + transports.Transport): max_size = 256 * 1024 # Buffer size passed to recv(). diff --git a/Lib/asyncio/transports.py b/Lib/asyncio/transports.py --- a/Lib/asyncio/transports.py +++ b/Lib/asyncio/transports.py @@ -219,3 +219,73 @@ http://docs.python.org/3/library/subprocess#subprocess.Popen.kill """ raise NotImplementedError + + +class _FlowControlMixin(Transport): + """All the logic for (write) flow control in a mix-in base class. + + The subclass must implement get_write_buffer_size(). It must call + _maybe_pause_protocol() whenever the write buffer size increases, + and _maybe_resume_protocol() whenever it decreases. It may also + override set_write_buffer_limits() (e.g. to specify different + defaults). + + The subclass constructor must call super().__init__(extra). This + will call set_write_buffer_limits(). + + The user may call set_write_buffer_limits() and + get_write_buffer_size(), and their protocol's pause_writing() and + resume_writing() may be called. + """ + + def __init__(self, extra=None): + super().__init__(extra) + self._protocol_paused = False + self.set_write_buffer_limits() + + def _maybe_pause_protocol(self): + size = self.get_write_buffer_size() + if size <= self._high_water: + return + if not self._protocol_paused: + self._protocol_paused = True + try: + self._protocol.pause_writing() + except Exception as exc: + self._loop.call_exception_handler({ + 'message': 'protocol.pause_writing() failed', + 'exception': exc, + 'transport': self, + 'protocol': self._protocol, + }) + + def _maybe_resume_protocol(self): + if (self._protocol_paused and + self.get_write_buffer_size() <= self._low_water): + self._protocol_paused = False + try: + self._protocol.resume_writing() + except Exception as exc: + self._loop.call_exception_handler({ + 'message': 'protocol.resume_writing() failed', + 'exception': exc, + 'transport': self, + 'protocol': self._protocol, + }) + + def set_write_buffer_limits(self, high=None, low=None): + if high is None: + if low is None: + high = 64*1024 + else: + 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)) + self._high_water = high + self._low_water = low + + def get_write_buffer_size(self): + raise NotImplementedError diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -317,7 +317,7 @@ self._loop = None -class _UnixWritePipeTransport(selector_events._FlowControlMixin, +class _UnixWritePipeTransport(transports._FlowControlMixin, transports.WriteTransport): def __init__(self, loop, pipe, protocol, waiter=None, extra=None): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 01:41:06 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 19 Feb 2014 01:41:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2C_Tulip_issue_139?= =?utf-8?q?=3A_Improve_error_messages_on_=22fatal_errors=22?= Message-ID: <3fTKqQ63CGz7Lqj@mail.python.org> http://hg.python.org/cpython/rev/2406566d2c04 changeset: 89264:2406566d2c04 user: Victor Stinner date: Wed Feb 19 01:40:41 2014 +0100 summary: asyncio, Tulip issue 139: Improve error messages on "fatal errors" Mention if the error was caused by a read or a write, and be more specific on the object (ex: "pipe transport" instead of "transport"). files: Lib/asyncio/proactor_events.py | 10 +- Lib/asyncio/selector_events.py | 22 +++-- Lib/asyncio/unix_events.py | 14 +- Lib/test/test_asyncio/test_proactor_events.py | 12 ++- Lib/test/test_asyncio/test_selector_events.py | 36 +++++++-- Lib/test/test_asyncio/test_unix_events.py | 8 +- 6 files changed, 64 insertions(+), 38 deletions(-) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -53,10 +53,10 @@ if self._read_fut is not None: self._read_fut.cancel() - def _fatal_error(self, exc): + def _fatal_error(self, exc, message='Fatal error on pipe transport'): if not isinstance(exc, (BrokenPipeError, ConnectionResetError)): self._loop.call_exception_handler({ - 'message': 'Fatal transport error', + 'message': message, 'exception': exc, 'transport': self, 'protocol': self._protocol, @@ -151,11 +151,11 @@ self._read_fut = self._loop._proactor.recv(self._sock, 4096) except ConnectionAbortedError as exc: if not self._closing: - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal read error on pipe transport') except ConnectionResetError as exc: self._force_close(exc) except OSError as exc: - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal read error on pipe transport') except futures.CancelledError: if not self._closing: raise @@ -246,7 +246,7 @@ except ConnectionResetError as exc: self._force_close(exc) except OSError as exc: - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal write error on pipe transport') def can_write_eof(self): return True diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -377,11 +377,11 @@ self._conn_lost += 1 self._loop.call_soon(self._call_connection_lost, None) - def _fatal_error(self, exc): + def _fatal_error(self, exc, message='Fatal error on transport'): # Should be called from exception handler only. if not isinstance(exc, (BrokenPipeError, ConnectionResetError)): self._loop.call_exception_handler({ - 'message': 'Fatal transport error', + 'message': message, 'exception': exc, 'transport': self, 'protocol': self._protocol, @@ -452,7 +452,7 @@ except (BlockingIOError, InterruptedError): pass except Exception as exc: - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal read error on socket transport') else: if data: self._protocol.data_received(data) @@ -488,7 +488,7 @@ except (BlockingIOError, InterruptedError): pass except Exception as exc: - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal write error on socket transport') return else: data = data[n:] @@ -511,7 +511,7 @@ except Exception as exc: self._loop.remove_writer(self._sock_fd) self._buffer.clear() - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal write error on socket transport') else: if n: del self._buffer[:n] @@ -678,7 +678,7 @@ self._loop.remove_reader(self._sock_fd) self._loop.add_writer(self._sock_fd, self._write_ready) except Exception as exc: - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal read error on SSL transport') else: if data: self._protocol.data_received(data) @@ -712,7 +712,7 @@ except Exception as exc: self._loop.remove_writer(self._sock_fd) self._buffer.clear() - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal write error on SSL transport') return if n: @@ -770,7 +770,7 @@ except OSError as exc: self._protocol.error_received(exc) except Exception as exc: - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal read error on datagram transport') else: self._protocol.datagram_received(data, addr) @@ -805,7 +805,8 @@ self._protocol.error_received(exc) return except Exception as exc: - self._fatal_error(exc) + self._fatal_error(exc, + 'Fatal write error on datagram transport') return # Ensure that what we buffer is immutable. @@ -827,7 +828,8 @@ self._protocol.error_received(exc) return except Exception as exc: - self._fatal_error(exc) + self._fatal_error(exc, + 'Fatal write error on datagram transport') return self._maybe_resume_protocol() # May append to buffer. diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -271,7 +271,7 @@ except (BlockingIOError, InterruptedError): pass except OSError as exc: - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal read error on pipe transport') else: if data: self._protocol.data_received(data) @@ -291,11 +291,11 @@ if not self._closing: self._close(None) - def _fatal_error(self, exc): + def _fatal_error(self, exc, message='Fatal error on pipe transport'): # should be called by exception handler only if not (isinstance(exc, OSError) and exc.errno == errno.EIO): self._loop.call_exception_handler({ - 'message': 'Fatal transport error', + 'message': message, 'exception': exc, 'transport': self, 'protocol': self._protocol, @@ -381,7 +381,7 @@ n = 0 except Exception as exc: self._conn_lost += 1 - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal write error on pipe transport') return if n == len(data): return @@ -406,7 +406,7 @@ # Remove writer here, _fatal_error() doesn't it # because _buffer is empty. self._loop.remove_writer(self._fileno) - self._fatal_error(exc) + self._fatal_error(exc, 'Fatal write error on pipe transport') else: if n == len(data): self._loop.remove_writer(self._fileno) @@ -443,11 +443,11 @@ def abort(self): self._close(None) - def _fatal_error(self, exc): + def _fatal_error(self, exc, message='Fatal error on pipe transport'): # should be called by exception handler only if not isinstance(exc, (BrokenPipeError, ConnectionResetError)): self._loop.call_exception_handler({ - 'message': 'Fatal transport error', + 'message': message, 'exception': exc, 'transport': self, 'protocol': self._protocol, diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -69,7 +69,9 @@ tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._fatal_error = unittest.mock.Mock() tr._loop_reading() - tr._fatal_error.assert_called_with(err) + tr._fatal_error.assert_called_with( + err, + 'Fatal read error on pipe transport') def test_loop_reading_aborted_closing(self): self.loop._proactor.recv.side_effect = ConnectionAbortedError() @@ -105,7 +107,9 @@ tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._fatal_error = unittest.mock.Mock() tr._loop_reading() - tr._fatal_error.assert_called_with(err) + tr._fatal_error.assert_called_with( + err, + 'Fatal read error on pipe transport') def test_write(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) @@ -142,7 +146,9 @@ tr._fatal_error = unittest.mock.Mock() tr._buffer = [b'da', b'ta'] tr._loop_writing() - tr._fatal_error.assert_called_with(err) + tr._fatal_error.assert_called_with( + err, + 'Fatal write error on pipe transport') tr._conn_lost = 1 tr.write(b'data') diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -655,7 +655,7 @@ m_exc.assert_called_with( test_utils.MockPattern( - 'Fatal transport error\nprotocol:.*\ntransport:.*'), + 'Fatal error on transport\nprotocol:.*\ntransport:.*'), exc_info=(OSError, MOCK_ANY, MOCK_ANY)) tr._force_close.assert_called_with(exc) @@ -785,7 +785,9 @@ transport._fatal_error = unittest.mock.Mock() transport._read_ready() - transport._fatal_error.assert_called_with(err) + transport._fatal_error.assert_called_with( + err, + 'Fatal read error on socket transport') def test_write(self): data = b'data' @@ -898,7 +900,9 @@ self.loop, self.sock, self.protocol) transport._fatal_error = unittest.mock.Mock() transport.write(data) - transport._fatal_error.assert_called_with(err) + transport._fatal_error.assert_called_with( + err, + 'Fatal write error on socket transport') transport._conn_lost = 1 self.sock.reset_mock() @@ -1001,7 +1005,9 @@ transport._fatal_error = unittest.mock.Mock() transport._buffer.extend(b'data') transport._write_ready() - transport._fatal_error.assert_called_with(err) + transport._fatal_error.assert_called_with( + err, + 'Fatal write error on socket transport') @unittest.mock.patch('asyncio.base_events.logger') def test_write_ready_exception_and_close(self, m_log): @@ -1237,7 +1243,9 @@ transport = self._make_one() transport._fatal_error = unittest.mock.Mock() transport._read_ready() - transport._fatal_error.assert_called_with(err) + transport._fatal_error.assert_called_with( + err, + 'Fatal read error on SSL transport') def test_write_ready_send(self): self.sslsock.send.return_value = 4 @@ -1319,7 +1327,9 @@ transport._buffer = list_to_buffer([b'data']) transport._fatal_error = unittest.mock.Mock() transport._write_ready() - transport._fatal_error.assert_called_with(err) + transport._fatal_error.assert_called_with( + err, + 'Fatal write error on SSL transport') self.assertEqual(list_to_buffer(), transport._buffer) def test_write_ready_read_wants_write(self): @@ -1407,7 +1417,9 @@ transport._fatal_error = unittest.mock.Mock() transport._read_ready() - transport._fatal_error.assert_called_with(err) + transport._fatal_error.assert_called_with( + err, + 'Fatal read error on datagram transport') def test_read_ready_oserr(self): transport = _SelectorDatagramTransport( @@ -1517,7 +1529,9 @@ transport.sendto(data, ()) self.assertTrue(transport._fatal_error.called) - transport._fatal_error.assert_called_with(err) + transport._fatal_error.assert_called_with( + err, + 'Fatal write error on datagram transport') transport._conn_lost = 1 transport._address = ('123',) @@ -1633,7 +1647,9 @@ transport._buffer.append((b'data', ())) transport._sendto_ready() - transport._fatal_error.assert_called_with(err) + transport._fatal_error.assert_called_with( + err, + 'Fatal write error on datagram transport') def test_sendto_ready_error_received(self): self.sock.sendto.side_effect = ConnectionRefusedError @@ -1667,7 +1683,7 @@ self.assertFalse(self.protocol.error_received.called) m_exc.assert_called_with( test_utils.MockPattern( - 'Fatal transport error\nprotocol:.*\ntransport:.*'), + 'Fatal error on transport\nprotocol:.*\ntransport:.*'), exc_info=(ConnectionRefusedError, MOCK_ANY, MOCK_ANY)) diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -365,7 +365,7 @@ tr._close.assert_called_with(err) m_logexc.assert_called_with( test_utils.MockPattern( - 'Fatal transport error\nprotocol:.*\ntransport:.*'), + 'Fatal read error on pipe transport\nprotocol:.*\ntransport:.*'), exc_info=(OSError, MOCK_ANY, MOCK_ANY)) @unittest.mock.patch('os.read') @@ -558,7 +558,9 @@ m_write.assert_called_with(5, b'data') self.assertFalse(self.loop.writers) self.assertEqual([], tr._buffer) - tr._fatal_error.assert_called_with(err) + tr._fatal_error.assert_called_with( + err, + 'Fatal write error on pipe transport') self.assertEqual(1, tr._conn_lost) tr.write(b'data') @@ -660,7 +662,7 @@ self.assertTrue(tr._closing) m_logexc.assert_called_with( test_utils.MockPattern( - 'Fatal transport error\nprotocol:.*\ntransport:.*'), + 'Fatal write error on pipe transport\nprotocol:.*\ntransport:.*'), exc_info=(OSError, MOCK_ANY, MOCK_ANY)) self.assertEqual(1, tr._conn_lost) test_utils.run_briefly(self.loop) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 01:46:09 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 19 Feb 2014 01:46:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2C_Tulip_issue_143?= =?utf-8?q?=3A_UNIX_domain_methods=2C_fix_ResourceWarning_and?= Message-ID: <3fTKxF26Vpz7LmF@mail.python.org> http://hg.python.org/cpython/rev/089ce5ddc147 changeset: 89265:089ce5ddc147 user: Victor Stinner date: Wed Feb 19 01:45:59 2014 +0100 summary: asyncio, Tulip issue 143: UNIX domain methods, fix ResourceWarning and DeprecationWarning warnings. create_unix_server() closes the socket on any error, not only on OSError. files: Lib/asyncio/unix_events.py | 8 +- Lib/test/test_asyncio/test_unix_events.py | 28 +++++----- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -183,13 +183,12 @@ raise ValueError( 'path and sock can not be specified at the same time') + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0) try: - sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0) sock.setblocking(False) yield from self.sock_connect(sock, path) - except OSError: - if sock is not None: - sock.close() + except: + sock.close() raise else: @@ -213,6 +212,7 @@ try: sock.bind(path) except OSError as exc: + sock.close() if exc.errno == errno.EADDRINUSE: # Let's improve the error message by adding # with what exact address it occurs. diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -221,17 +221,17 @@ with test_utils.unix_socket_path() as path: sock = socket.socket(socket.AF_UNIX) sock.bind(path) - - coro = self.loop.create_unix_server(lambda: None, path) - with self.assertRaisesRegexp(OSError, - 'Address.*is already in use'): - self.loop.run_until_complete(coro) + with sock: + coro = self.loop.create_unix_server(lambda: None, path) + with self.assertRaisesRegex(OSError, + 'Address.*is already in use'): + self.loop.run_until_complete(coro) def test_create_unix_server_existing_path_nonsock(self): with tempfile.NamedTemporaryFile() as file: coro = self.loop.create_unix_server(lambda: None, file.name) - with self.assertRaisesRegexp(OSError, - 'Address.*is already in use'): + with self.assertRaisesRegex(OSError, + 'Address.*is already in use'): self.loop.run_until_complete(coro) def test_create_unix_server_ssl_bool(self): @@ -248,11 +248,13 @@ self.loop.run_until_complete(coro) def test_create_unix_server_path_inetsock(self): - coro = self.loop.create_unix_server(lambda: None, path=None, - sock=socket.socket()) - with self.assertRaisesRegex(ValueError, - 'A UNIX Domain Socket was expected'): - self.loop.run_until_complete(coro) + sock = socket.socket() + with sock: + coro = self.loop.create_unix_server(lambda: None, path=None, + sock=sock) + with self.assertRaisesRegex(ValueError, + 'A UNIX Domain Socket was expected'): + self.loop.run_until_complete(coro) def test_create_unix_connection_path_sock(self): coro = self.loop.create_unix_connection( @@ -278,7 +280,7 @@ coro = self.loop.create_unix_connection( lambda: None, '/dev/null', ssl=True) - with self.assertRaisesRegexp( + with self.assertRaisesRegex( ValueError, 'you have to pass server_hostname when using ssl'): self.loop.run_until_complete(coro) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 02:21:32 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 19 Feb 2014 02:21:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320682=3A_test=5Fa?= =?utf-8?q?syncio=2C_=5Fbasetest=5Fcreate=5Fconnection=28=29_checks_also_t?= =?utf-8?q?he?= Message-ID: <3fTLk41jn2z7LmF@mail.python.org> http://hg.python.org/cpython/rev/64ad965a2fd4 changeset: 89266:64ad965a2fd4 user: Victor Stinner date: Wed Feb 19 02:21:08 2014 +0100 summary: Issue #20682: test_asyncio, _basetest_create_connection() checks also the sockname, as _basetest_create_ssl_connection(). files: Lib/test/test_asyncio/test_events.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -503,6 +503,7 @@ tr, pr = self.loop.run_until_complete(connection_fut) self.assertIsInstance(tr, asyncio.Transport) self.assertIsInstance(pr, asyncio.Protocol) + self.assertIsNotNone(tr.get_extra_info('sockname')) self.loop.run_until_complete(pr.done) self.assertGreater(pr.nbytes, 0) tr.close() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 04:28:14 2014 From: python-checkins at python.org (yury.selivanov) Date: Wed, 19 Feb 2014 04:28:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Fix_spelling_an?= =?utf-8?q?d_typos=2E?= Message-ID: <3fTPXG4SBJz7LjX@mail.python.org> http://hg.python.org/cpython/rev/2b0e65df8821 changeset: 89267:2b0e65df8821 user: Yury Selivanov date: Tue Feb 18 22:27:48 2014 -0500 summary: asyncio: Fix spelling and typos. Thanks to Vajrasky Kok for discovering some of them. files: Lib/asyncio/events.py | 6 +++--- Lib/asyncio/protocols.py | 2 +- Lib/asyncio/selector_events.py | 2 +- Lib/asyncio/tasks.py | 2 +- Lib/asyncio/test_utils.py | 4 ++-- Lib/asyncio/unix_events.py | 4 ++-- Lib/asyncio/windows_events.py | 2 +- Lib/selectors.py | 2 +- Lib/test/test_asyncio/test_base_events.py | 2 +- Lib/test/test_asyncio/test_events.py | 1 - Lib/test/test_asyncio/test_futures.py | 2 +- Lib/test/test_asyncio/test_streams.py | 2 +- Lib/test/test_asyncio/test_unix_events.py | 6 +++--- 13 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -235,7 +235,7 @@ sock=None, backlog=100, ssl=None): """A coroutine which creates a UNIX Domain Socket server. - The return valud is a Server object, which can be used to stop + The return value is a Server object, which can be used to stop the service. path is a str, representing a file systsem path to bind the @@ -260,7 +260,7 @@ # Pipes and subprocesses. def connect_read_pipe(self, protocol_factory, pipe): - """Register read pipe in eventloop. + """Register read pipe in event loop. protocol_factory should instantiate object with Protocol interface. pipe is file-like object already switched to nonblocking. @@ -273,7 +273,7 @@ raise NotImplementedError def connect_write_pipe(self, protocol_factory, pipe): - """Register write pipe in eventloop. + """Register write pipe in event loop. protocol_factory should instantiate object with BaseProtocol interface. Pipe is file-like object already switched to nonblocking. diff --git a/Lib/asyncio/protocols.py b/Lib/asyncio/protocols.py --- a/Lib/asyncio/protocols.py +++ b/Lib/asyncio/protocols.py @@ -114,7 +114,7 @@ def pipe_data_received(self, fd, data): """Called when the subprocess writes data into stdout/stderr pipe. - fd is int file dascriptor. + fd is int file descriptor. data is bytes object. """ diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -213,7 +213,7 @@ def _sock_recv(self, fut, registered, sock, n): # _sock_recv() can add itself as an I/O callback if the operation can't - # be done immediatly. Don't use it directly, call sock_recv(). + # be done immediately. Don't use it directly, call sock_recv(). fd = sock.fileno() if registered: # Remove the callback early. It should be rare that the diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -181,7 +181,7 @@ The frames are always ordered from oldest to newest. - The optional limit gives the maximum nummber of frames to + The optional limit gives the maximum number of frames to return; by default all available frames are returned. Its meaning differs depending on whether a stack or a traceback is returned: the newest frames of a stack are returned, but the diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -259,7 +259,7 @@ when = yield ... ... = yield time_advance - Value retuned by yield is absolute time of next scheduled handler. + Value returned by yield is absolute time of next scheduled handler. Value passed to yield is time advance to move loop's time forward. """ @@ -369,7 +369,7 @@ """A regex based str with a fuzzy __eq__. Use this helper with 'mock.assert_called_with', or anywhere - where a regexp comparison between strings is needed. + where a regex comparison between strings is needed. For instance: mock_call.assert_called_with(MockPattern('spam.*ham')) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -1,4 +1,4 @@ -"""Selector eventloop for Unix with signal handling.""" +"""Selector event loop for Unix with signal handling.""" import errno import fcntl @@ -244,7 +244,7 @@ class _UnixReadPipeTransport(transports.ReadTransport): - max_size = 256 * 1024 # max bytes we read in one eventloop iteration + max_size = 256 * 1024 # max bytes we read in one event loop iteration def __init__(self, loop, pipe, protocol, waiter=None, extra=None): super().__init__(extra) diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -1,4 +1,4 @@ -"""Selector and proactor eventloops for Windows.""" +"""Selector and proactor event loops for Windows.""" import _winapi import errno diff --git a/Lib/selectors.py b/Lib/selectors.py --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -80,7 +80,7 @@ A selector can use various implementations (select(), poll(), epoll()...) depending on the platform. The default `Selector` class uses the most - performant implementation on the current platform. + efficient implementation on the current platform. """ @abstractmethod diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -277,7 +277,7 @@ asyncio.SubprocessProtocol, *args, bufsize=4096) def test_subprocess_shell_invalid_args(self): - # exepected a string, not an int or a list + # expected a string, not an int or a list self.assertRaises(TypeError, self.loop.run_until_complete, self.loop.subprocess_shell, asyncio.SubprocessProtocol, 123) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -503,7 +503,6 @@ tr, pr = self.loop.run_until_complete(connection_fut) self.assertIsInstance(tr, asyncio.Transport) self.assertIsInstance(pr, asyncio.Protocol) - self.assertIsNotNone(tr.get_extra_info('sockname')) self.loop.run_until_complete(pr.done) self.assertGreater(pr.nbytes, 0) tr.close() diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -38,7 +38,7 @@ asyncio.set_event_loop(None) def test_constructor_positional(self): - # Make sure Future does't accept a positional argument + # Make sure Future doesn't accept a positional argument self.assertRaises(TypeError, asyncio.Future, 42) def test_cancel(self): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -239,7 +239,7 @@ # No b'\n' at the end. The 'limit' is set to 3. So before # waiting for the new data in buffer, 'readline' will consume # the entire buffer, and since the length of the consumed data - # is more than 3, it will raise a ValudError. The buffer is + # is more than 3, it will raise a ValueError. The buffer is # expected to be empty now. self.assertEqual(b'', stream._buffer) diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -965,7 +965,7 @@ self.assertFalse(m.WEXITSTATUS.called) self.assertFalse(m.WTERMSIG.called) - # childen are running + # children are running self.watcher._sig_chld() self.assertFalse(callback1.called) @@ -1069,7 +1069,7 @@ self.assertFalse(m.WEXITSTATUS.called) self.assertFalse(m.WTERMSIG.called) - # childen are running + # children are running self.watcher._sig_chld() self.assertFalse(callback1.called) @@ -1425,7 +1425,7 @@ self.add_zombie(61, 11) self.add_zombie(62, -5) - # SIGCHLD was not catched + # SIGCHLD was not caught self.assertFalse(callback1.called) self.assertFalse(callback2.called) self.assertFalse(callback3.called) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 04:49:25 2014 From: python-checkins at python.org (larry.hastings) Date: Wed, 19 Feb 2014 04:49:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?release=3A_Major_updates_for_my_local?= =?utf-8?q?_3=2E4_build_tool=2E?= Message-ID: <3fTQ0j66q6z7Lk7@mail.python.org> http://hg.python.org/release/rev/77e1e7cfbc7d changeset: 72:77e1e7cfbc7d user: Larry Hastings date: Tue Feb 18 19:49:22 2014 -0800 summary: Major updates for my local 3.4 build tool. files: 3.4/threefourtool.py | 346 +++++++++++++++++++++--------- 1 files changed, 241 insertions(+), 105 deletions(-) diff --git a/3.4/threefourtool.py b/3.4/threefourtool.py --- a/3.4/threefourtool.py +++ b/3.4/threefourtool.py @@ -4,15 +4,33 @@ import collections import datetime from dryparse import dryparse +import glob import os import pprint import pickle +import shutil import subprocess import sys import tempfile import time +outgoing = "/home/larry/src/python/34outgoing" + + +def yes_no(): + while True: + s = input("Are you sure? (y/n) >") + if s.strip() in 'yn': + return s + + +def now(): + s = str(datetime.datetime.now()) + for c in "- :": + s = s.replace(c, '.') + return s + def line_to_rev(line): if line.startswith("changeset:"): line = line[len("changeset:"):].strip() @@ -24,6 +42,7 @@ # print(repr(line), rev) return local, rev + changesets = collections.OrderedDict() user_date_to_revs = {} # "user date" == "{user} {date}", maps to (rev, branch) default_to_34 = {} # maps rev in default to rev in 3.4 @@ -31,10 +50,18 @@ revs = [] branches = {} +def reset_changesets(): + changesets.clear() + user_date_to_revs.clear() + default_to_34.clear() + default_from_34.clear() + revs.clear() + branches.clear() + def line_iterator(pipe, encoding='utf-8'): text = b'' while True: - got = pipe.read(4096) + got = pipe.read(128) if not got: break # print("GOT", repr(got)) @@ -73,10 +100,12 @@ def get_user_date_to_revs(fields): return user_date_to_revs[fields['user'] + ' ' + fields['date']] -def read_changesets(earliest = '6343bdbb7085'): - if changesets: +def read_changesets(earliest = '6343bdbb7085', force=False): + if changesets and not force: return + reset_changesets() + p = None current_directory = os.getcwd() try: @@ -133,6 +162,7 @@ revs.append(rev) if not branch in branches: branches[branch] = [] + assert rev not in branches[branch], "Adding rev " + rev + " twice to branch " + repr(branch) + "!" branches[branch].append(rev) if rev == earliest: break @@ -150,7 +180,7 @@ default_from_34[d['3.4']] = d[None] def header(category, printer): - print(category) + # print(category) printer("""

{}

@@ -161,7 +191,6 @@
""") - def print_rev(rev, printer): fields = changesets[rev] d = dict(fields) @@ -169,7 +198,7 @@ d['rev'] = rev d['description0'] = description[0] d['description1+'] = "
\n".join(description[1:]) - print(" r", rev) + # print(" r", rev) printer(""" @@ -200,10 +229,12 @@ seen = set() for rev, fields in changesets.items(): - print(" :", rev) + # print(" :", rev) rev_to_print = print_test(rev) if rev_to_print: break + else: + return print_rev(rev_to_print, printer) seen.add(rev_to_print) @@ -214,21 +245,21 @@ hopper.sort() parents = fields['parents'] - print(" r", rev, "p", parents) + # print(" r", rev, "p", parents) refill_hopper(parents) while hopper: _, rev = hopper.pop(0) - print(" ?", rev) + # print(" ?", rev) if not lineage_test(rev): continue fields = changesets[rev] parents = fields['parents'] - print(" r", rev, "p", parents) refill_hopper(parents) rev_to_print = print_test(rev) if not rev_to_print: continue + # print(" r", rev, "p", parents, "rev to print", rev_to_print) if rev_to_print in seen: continue seen.add(rev_to_print) @@ -252,17 +283,17 @@ return rev def is_34(rev): - # if rev == '6343bdbb7085': - # raise StopIteration() fields = changesets[rev] branch = fields.get('branch') if branch != '3.4': return False revs = get_user_date_to_revs(fields) assert (rev, branch) in revs - for rev, branch in revs: + # print("is 34?", rev, revs) + for r2, branch in revs: if not branch: - return rev + # print(rev, "->", r2) + return r2 return False class Tool: @@ -296,7 +327,7 @@ """ Regenerate the status webpage. """ - f = open("/home/larry/src/python/3.4.merge.status.html", "wt") + f = open(outgoing + "/merge.status.html", "wt") read_changesets() @@ -328,7 +359,7 @@

""") - printer("
Notice: this is BETA (don't take it seriously yet)
") + # printer("
Notice: this is BETA (don't take it seriously yet)
") header("Merged", printer) print_revs(is_34, is_34, printer) footer(printer) @@ -350,20 +381,12 @@ f.close() - def _run_commands(self, commands, u): + def _run_command(self, commands, u): commands_run = u['commands run'] - def done(): - self.unfinished = None - self._abandon() - sys.exit(0) - - done_tuple = ("Done!", done) - if done_tuple not in commands: - commands.append(done_tuple) while True: print("Commands:") - commands_set = set('h.d') + commands_set = set('h.dq') for i, (text, cmd) in enumerate(commands): label = str(i+1) commands_set.add(label) @@ -387,6 +410,8 @@ pprint.pprint(u) print() continue + if s == 'q': + return if s == 'h': print(""" Simple help @@ -394,6 +419,7 @@ . - repeat the command menu h - print this help message d - print the internal "unfinished" dict +q - quit """) continue break @@ -409,74 +435,154 @@ else: cmd() - def pick(self, picked_revision): + def pick(self, picked_revision, *picked_revisions): """ Cherry-pick a revision from default to 3.4. """ + pr = [picked_revision] + pr.extend(picked_revisions) + picked_revisions = pr + + read_changesets() + + # sort earliest first + for rev in picked_revisions: + if rev not in branches[None]: + sys.exit("Can't pick revision " + rev + ", it's not in default.") + + def to_default_index(rev): + # revisions are sorted latest first, + # we want the opposite, so we negate + return -branches[None].index(rev) + picked_revisions.sort(key=to_default_index) + if self.unfinished: - if self.unfinished['default picked revision'] == picked_revision: + if self.unfinished['original picked revisions'] == picked_revisions: return self.finish() sys.exit("You have unfinished business!\n\nUse the 'finish' command to finish it,\nor the 'abandon' command to abandon it.") - print("Picking revision", repr(picked_revision)) - read_changesets() - # changesets = collections.OrderedDict() - # user_date_to_revs = {} # "user date" == "{user} {date}", maps to (rev, branch) - # revs = [] - # branches = {} - try: - index = branches[None].index(picked_revision) - except ValueError: - sys.exit("{} is not a revision in Python trunk.".format(picked_revision)) - r_34_head = branches['3.4'][0] - r_34_first_revision = branches['3.4'][-1] - # print("index", index) - # print("3.4 branch", branches['3.4']) - # print("default_from_34", default_from_34) - r_previous = None - # find where it should go in 3.4 - for r in branches['3.4']: - # print("r", r) - if r == r_34_first_revision: - break - r_default = default_from_34[r] - i = branches[None].index(r_default) - if i == index: - sys.exit("{} already in 3.4!".format(picked_revision)) - if i > index: - break - r_previous = r - else: - sys.exit("Unexpected non-termination in pick!") - - if r == r_34_head: - r_rebase_from = None - else: - r_rebase_from = r_previous - - # figure out previous revision in default, in case we need to make a patch - diff_from = branches[None][index + 1] - - fields = changesets[picked_revision] - self.unfinished = { 'function': '_pick', - 'threefour rebase from': r_rebase_from, - 'threefour graft here': r, - 'default picked revision': picked_revision, - 'user': fields['user'], - 'date': fields['date'], - 'description': '\n'.join(fields['description']), - 'default diff from': diff_from, - 'threefour picked revision': 'UNKNOWN (detect via "Detect new revision")', - 'commands run': set(), + 'picked revisions': picked_revisions, + 'original picked revisions': list(picked_revisions), } self.finish() + + def _analyze_picked_revision(self): + read_changesets(force=True) + picked_revisions = self.unfinished['picked revisions'] + # print("picked_revisions", picked_revisions) + while picked_revisions: + # changesets = collections.OrderedDict() + # user_date_to_revs = {} # "user date" == "{user} {date}", maps to (rev, branch) + # revs = [] + # branches = {} + picked_revision = picked_revisions[0] + try: + index = branches[None].index(picked_revision) + except ValueError: + sys.exit("{} is not a revision in Python trunk.".format(picked_revision)) + r_34_head = branches['3.4'][0] + r_34_first_revision = branches['3.4'][-1] + # print("index", index) + # print("3.4 branch", branches['3.4']) + # print("default_from_34", default_from_34) + r_previous = None + # find where it should go in 3.4 + i = None + for r in branches['3.4']: + # print("r", r) + if r == r_34_first_revision: + break + r_default = default_from_34[r] + i = branches[None].index(r_default) + if i >= index: + break + r_previous = r + else: + sys.exit("Unexpected non-termination when searching for right spot to graft to!") + + if i == index: + print("{} already in 3.4!".format(picked_revision)) + picked_revisions.pop(0) + continue + + if r == r_34_head: + r_rebase_from = None + else: + r_rebase_from = r_previous + + # print("chose r", r, "r_34_head", r_34_head, "r_rebase_from", r_rebase_from) + + + # figure out previous revision in default, in case we need to make a patch + diff_from = branches[None][index + 1] + + fields = changesets[picked_revision] + + u2 = dict(self.unfinished) + + if 'done' in u2: + del u2['done'] + + u2.update({ + 'threefour rebase from': r_rebase_from, + 'threefour graft here': r, + 'default picked revision': picked_revision, + 'user': fields['user'], + 'date': fields['date'], + 'description': '\n'.join(fields['description']), + 'default diff from': diff_from, + 'threefour picked revision': 'UNKNOWN (detect via "Detect new revision")', + 'commands run': set(), + }) + picked_revisions.pop(0) + self.unfinished = u2 + break + def _pick(self): + read_changesets() os.chdir("/home/larry/src/python/3.4") + print("Updating to 3.4 branch:") + os.system("hg update -r 3.4") + print() + u = self.unfinished.get + print("Picking revisions ", u('picked revisions')) + while True: + picked_revisions = u('picked revisions') + if not picked_revisions: + break + if 'default picked revision' not in self.unfinished: + self._analyze_picked_revision() + if 'default picked revision' in self.unfinished: + self._pick_revision() + if not u('picked revisions'): + self._abandon() + + def _pick_revision(self): u = self.unfinished + u['EDITOR'] = os.getenv('EDITOR') + + patch_path = "/tmp/patch.{default diff from}.to.{default picked revision}.diff".format_map(u) + u['patch path'] = patch_path + + f, commit_message_path = tempfile.mkstemp(suffix='txt') + os.close(f) + with open(commit_message_path, 'wt') as f: + f.write(u['description']) + u['commit message path'] = commit_message_path + + def delete_files(*a): + for path in a: + try: + os.unlink(path) + except OSError: + pass + + atexit.register(delete_files, patch_path, commit_message_path) + def detect_new_revision(): output = subprocess.check_output(['/usr/bin/hg', 'summary']).decode('utf-8').split('\n') line = output[0] @@ -487,26 +593,10 @@ r = r.split()[0].strip() u['threefour picked revision'] = r - while True: - patch_path = "/tmp/patch.{default diff from}.to.{default picked revision}.diff".format_map(u) - u['patch path'] = patch_path + def mark_as_picked(): + del self.unfinished['default picked revision'] - f, commit_message_path = tempfile.mkstemp(suffix='txt') - os.close(f) - with open(commit_message_path, 'wt') as f: - f.write(u['description']) - u['commit message path'] = commit_message_path - - def delete_files(*a): - for path in a: - try: - os.unlink(path) - except OSError: - pass - - atexit.register(delete_files, patch_path, commit_message_path) - - u['EDITOR'] = os.getenv('EDITOR') + while u.get('default picked revision'): commands = [] commands.append(("Update to appropriate revision in 3.4 branch", "hg update -r {threefour graft here}")) @@ -521,10 +611,13 @@ commands.append(("Detect new revision", detect_new_revision)) c = "hg rebase --source {threefour rebase from} --dest {threefour picked revision}" commands.append(("Rebase subsequent revisions after grafted revision", c)) + commands.append(("Update to head of 3.4 branch", "hg update -r 3.4")) - commands.append(("Update to head of 3.4 branch", "hg update -r 3.4")) + commands.append(("Mark revision as picked", mark_as_picked)) - self._run_commands(commands, u) + print() + print("Picking revision {default picked revision}:".format_map(u)) + self._run_command(commands, u) def finish(self): try: @@ -540,16 +633,59 @@ except KeyboardInterrupt: self._save() - def abandon(self): + def abandon(self, *, force:('-f',)=False): if not self.unfinished: sys.exit("No unfinished business!") - while True: - s = input("Are you sure? (y/n) >") - if s.strip() in 'yn': - break - if s == 'y': + if force or yes_no() == 'y': self._abandon() + def recreate(self, *, force:('-f',)=False): + """ + Recreate the 3.4 branch from scratch. + """ + if (not force) and (yes_no() == 'n'): + sys.exit() + os.chdir("/home/larry/src/python") + while True: + if os.path.isdir("/home/larry/src/python/bad3.4"): + shutil.rmtree("/home/larry/src/python/bad3.4") + continue + if os.path.isdir("/home/larry/src/python/3.4"): + os.rename("/home/larry/src/python/3.4", "/home/larry/src/python/bad3.4") + continue + break + os.system("hg clone trunk 3.4") + os.chdir("/home/larry/src/python/3.4") + os.system("hg update -r e64ae8b82672") + os.system("hg branch 3.4") + os.system("hg commit -m 'Created release branch for 3.4.'") + + def tar(self): + time = now() + tardir = "/home/larry/src/python/python-" + time + def remove_dir(dir): + if os.path.isdir(dir): + shutil.rmtree(dir) + if os.path.isdir(dir): + sys.exit("Couldn't remove directory" + repr(dir)) + remove_dir(tardir) + + os.chdir("/home/larry/src/python") + os.system("hg clone 3.4 " + tardir) + + os.chdir(tardir) + remove_dir(".hg") + for prefix in ('.hg', '.bzr', '.git'): + for filename in glob.glob(prefix + '*'): + os.unlink(filename) + os.chdir("/home/larry/src/python") + os.system("tar cvfz " + outgoing + "/python.3.4.{}.tgz python-{}".format(time, time)) + + remove_dir(tardir) + + def rsync(self): + os.chdir(outgoing) + os.system("rsync -av * midwinter.com:public_html/3.4.status") -- Repository URL: http://hg.python.org/release From python-checkins at python.org Wed Feb 19 04:56:30 2014 From: python-checkins at python.org (yury.selivanov) Date: Wed, 19 Feb 2014 04:56:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_pep8-ify_the_co?= =?utf-8?b?ZGUu?= Message-ID: <3fTQ8t6sl8z7LnN@mail.python.org> http://hg.python.org/cpython/rev/2e8a142dbccc changeset: 89268:2e8a142dbccc user: Yury Selivanov date: Tue Feb 18 22:56:15 2014 -0500 summary: asyncio: pep8-ify the code. files: Lib/asyncio/base_events.py | 11 +++++---- Lib/asyncio/subprocess.py | 5 ++- Lib/test/test_asyncio/test_subprocess.py | 12 +++++++++- Lib/test/test_asyncio/test_tasks.py | 4 ++- Lib/test/test_asyncio/test_unix_events.py | 6 +++- 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -605,10 +605,10 @@ return transport, protocol @tasks.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): + 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: @@ -623,7 +623,8 @@ % type(arg).__name__) protocol = protocol_factory() transport = yield from self._make_subprocess_transport( - protocol, popen_args, False, stdin, stdout, stderr, bufsize, **kwargs) + protocol, popen_args, False, stdin, stdout, stderr, + bufsize, **kwargs) return transport, protocol def set_exception_handler(self, handler): diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -180,8 +180,9 @@ return Process(transport, protocol, loop) @tasks.coroutine -def create_subprocess_exec(program, *args, stdin=None, stdout=None, stderr=None, - loop=None, limit=streams._DEFAULT_LIMIT, **kwds): +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, diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -21,6 +21,7 @@ 'sys.stdout.buffer.write(data)'))] class SubprocessMixin: + def test_stdin_stdout(self): args = PROGRAM_CAT @@ -132,6 +133,7 @@ if sys.platform != 'win32': # Unix class SubprocessWatcherMixin(SubprocessMixin): + Watcher = None def setUp(self): @@ -151,14 +153,20 @@ self.loop.close() policy.set_event_loop(None) - class SubprocessSafeWatcherTests(SubprocessWatcherMixin, unittest.TestCase): + class SubprocessSafeWatcherTests(SubprocessWatcherMixin, + unittest.TestCase): + Watcher = unix_events.SafeChildWatcher - class SubprocessFastWatcherTests(SubprocessWatcherMixin, unittest.TestCase): + class SubprocessFastWatcherTests(SubprocessWatcherMixin, + unittest.TestCase): + Watcher = unix_events.FastChildWatcher + else: # Windows class SubprocessProactorTests(SubprocessMixin, unittest.TestCase): + def setUp(self): policy = asyncio.get_event_loop_policy() self.loop = asyncio.ProactorEventLoop() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -876,6 +876,7 @@ self.assertEqual(set(f.result() for f in done), {'a', 'b'}) def test_as_completed_duplicate_coroutines(self): + @asyncio.coroutine def coro(s): return s @@ -884,7 +885,8 @@ def runner(): result = [] c = coro('ham') - for f in asyncio.as_completed([c, c, coro('spam')], loop=self.loop): + for f in asyncio.as_completed([c, c, coro('spam')], + loop=self.loop): result.append((yield from f)) return result diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -367,7 +367,8 @@ tr._close.assert_called_with(err) m_logexc.assert_called_with( test_utils.MockPattern( - 'Fatal read error on pipe transport\nprotocol:.*\ntransport:.*'), + 'Fatal read error on pipe transport' + '\nprotocol:.*\ntransport:.*'), exc_info=(OSError, MOCK_ANY, MOCK_ANY)) @unittest.mock.patch('os.read') @@ -664,7 +665,8 @@ self.assertTrue(tr._closing) m_logexc.assert_called_with( test_utils.MockPattern( - 'Fatal write error on pipe transport\nprotocol:.*\ntransport:.*'), + 'Fatal write error on pipe transport' + '\nprotocol:.*\ntransport:.*'), exc_info=(OSError, MOCK_ANY, MOCK_ANY)) self.assertEqual(1, tr._conn_lost) test_utils.run_briefly(self.loop) -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Wed Feb 19 10:01:30 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 19 Feb 2014 10:01:30 +0100 Subject: [Python-checkins] Daily reference leaks (64ad965a2fd4): sum=59 Message-ID: results for 64ad965a2fd4 on branch "default" -------------------------------------------- test_multiprocessing_fork leaked [38, 0, 0] references, sum=38 test_multiprocessing_fork leaked [17, 0, 0] memory blocks, sum=17 test_site leaked [2, 0, 0] references, sum=2 test_site leaked [2, 0, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogyMlsMK', '-x'] From python-checkins at python.org Wed Feb 19 13:32:43 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 19 Feb 2014 13:32:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_document_new_cr?= =?utf-8?q?eate=5Funix=5Fconnection=28=29_and_create=5Funix=5Fserver=28=29?= =?utf-8?q?_methods?= Message-ID: <3fTdcW1xd3zLrD@mail.python.org> http://hg.python.org/cpython/rev/9cfb3d1cf0d1 changeset: 89269:9cfb3d1cf0d1 user: Victor Stinner date: Wed Feb 19 13:32:34 2014 +0100 summary: asyncio: document new create_unix_connection() and create_unix_server() methods of BaseEventLoop files: Doc/library/asyncio-eventloop.rst | 43 ++++++++++++++++-- 1 files changed, 38 insertions(+), 5 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -201,8 +201,10 @@ .. method:: BaseEventLoop.create_connection(protocol_factory, host=None, port=None, \*, ssl=None, family=0, proto=0, flags=0, sock=None, local_addr=None, server_hostname=None) Create a streaming transport connection to a given Internet *host* and - *port*. *protocol_factory* must be a callable returning a - :ref:`protocol ` instance. + *port*: socket family :py:data:`~socket.AF_INET` or + :py:data:`~socket.AF_INET6` depending on *host* (or *family* if specified), + socket type :py:data:`~socket.SOCK_STREAM`. *protocol_factory* must be a + callable returning a :ref:`protocol ` instance. This method returns a :ref:`coroutine object ` which will try to establish the connection in the background. When successful, the @@ -265,6 +267,35 @@ (:class:`StreamReader`, :class:`StreamWriter`) instead of a protocol. +.. method:: BaseEventLoop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, \*, family=0, proto=0, flags=0) + + Create datagram connection: socket family :py:data:`~socket.AF_INET` or + :py:data:`~socket.AF_INET6` depending on *host* (or *family* if specified), + socket type :py:data:`~socket.SOCK_DGRAM`. + + This method returns a :ref:`coroutine object ` which will try to + establish the connection in the background. When successful, the + coroutine returns a ``(transport, protocol)`` pair. + + See the :meth:`BaseEventLoop.create_connection` method for parameters. + + +.. method:: BaseEventLoop.create_unix_connection(protocol_factory, path, \*, ssl=None, sock=None, server_hostname=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 + family is used to communicate between processes on the same machine + efficiently. + + This method returns a :ref:`coroutine object ` which will try to + establish the connection in the background. When successful, the + coroutine returns a ``(transport, protocol)`` pair. + + See the :meth:`BaseEventLoop.create_connection` method for parameters. + + Availability: UNIX. + + Creating listening connections ------------------------------ @@ -307,11 +338,13 @@ The function :func:`start_server` creates a (:class:`StreamReader`, :class:`StreamWriter`) pair and calls back a function with this pair. -.. method:: BaseEventLoop.create_datagram_endpoint(protocol_factory, local_addr=None, remote_addr=None, \*, family=0, proto=0, flags=0) - Create datagram connection. +.. method:: BaseEventLoop.create_unix_server(protocol_factory, path=None, \*, sock=None, backlog=100, ssl=None) - This method returns a :ref:`coroutine object `. + Similar to :meth:`BaseEventLoop.create_server`, but specific to the + socket family :py:data:`~socket.AF_UNIX`. + + Availability: UNIX. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 17:11:09 2014 From: python-checkins at python.org (yury.selivanov) Date: Wed, 19 Feb 2014 17:11:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_WriteTransport?= =?utf-8?q?=2Eset=5Fwrite=5Fbuffer=5Fsize_to_call_=5Fmaybe=5Fpause=5Fproto?= =?utf-8?q?col?= Message-ID: <3fTkSY41KJz7LjY@mail.python.org> http://hg.python.org/cpython/rev/186f6f56f4bc changeset: 89270:186f6f56f4bc user: Yury Selivanov date: Wed Feb 19 11:10:52 2014 -0500 summary: asyncio: WriteTransport.set_write_buffer_size to call _maybe_pause_protocol files: Lib/asyncio/transports.py | 8 +++- Lib/test/test_asyncio/test_transports.py | 23 ++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/transports.py b/Lib/asyncio/transports.py --- a/Lib/asyncio/transports.py +++ b/Lib/asyncio/transports.py @@ -241,7 +241,7 @@ def __init__(self, extra=None): super().__init__(extra) self._protocol_paused = False - self.set_write_buffer_limits() + self._set_write_buffer_limits() def _maybe_pause_protocol(self): size = self.get_write_buffer_size() @@ -273,7 +273,7 @@ 'protocol': self._protocol, }) - def set_write_buffer_limits(self, high=None, low=None): + def _set_write_buffer_limits(self, high=None, low=None): if high is None: if low is None: high = 64*1024 @@ -287,5 +287,9 @@ self._high_water = high self._low_water = low + def set_write_buffer_limits(self, high=None, low=None): + self._set_write_buffer_limits(high=high, low=low) + self._maybe_pause_protocol() + def get_write_buffer_size(self): raise NotImplementedError diff --git a/Lib/test/test_asyncio/test_transports.py b/Lib/test/test_asyncio/test_transports.py --- a/Lib/test/test_asyncio/test_transports.py +++ b/Lib/test/test_asyncio/test_transports.py @@ -4,6 +4,7 @@ import unittest.mock import asyncio +from asyncio import transports class TransportTests(unittest.TestCase): @@ -60,6 +61,28 @@ self.assertRaises(NotImplementedError, transport.terminate) self.assertRaises(NotImplementedError, transport.kill) + def test_flowcontrol_mixin_set_write_limits(self): + + class MyTransport(transports._FlowControlMixin, + transports.Transport): + + def get_write_buffer_size(self): + return 512 + + transport = MyTransport() + transport._protocol = unittest.mock.Mock() + + self.assertFalse(transport._protocol_paused) + + with self.assertRaisesRegex(ValueError, 'high.*must be >= low'): + transport.set_write_buffer_limits(high=0, low=1) + + transport.set_write_buffer_limits(high=1024, low=128) + self.assertFalse(transport._protocol_paused) + + transport.set_write_buffer_limits(high=256, low=128) + self.assertTrue(transport._protocol_paused) + if __name__ == '__main__': unittest.main() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 17:35:46 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 19 Feb 2014 17:35:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogRml4ZWQgZ3JpZF9j?= =?utf-8?q?olumnconfigure=28=29_and_grid=5Frowconfigure=28=29_methods_of?= Message-ID: <3fTl0y60Pgz7Ljy@mail.python.org> http://hg.python.org/cpython/rev/857ddbaff14e changeset: 89271:857ddbaff14e branch: 2.7 parent: 89249:63f0a1e95d2b user: Serhiy Storchaka date: Wed Feb 19 18:33:30 2014 +0200 summary: Fixed grid_columnconfigure() and grid_rowconfigure() methods of Tkinter widgets to work in wantobjects=True mode. files: Lib/lib-tk/Tkinter.py | 29 ++++++++++++++++++----------- Misc/NEWS | 3 +++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Lib/lib-tk/Tkinter.py b/Lib/lib-tk/Tkinter.py --- a/Lib/lib-tk/Tkinter.py +++ b/Lib/lib-tk/Tkinter.py @@ -1336,6 +1336,21 @@ return self._getints(self.tk.call(*args)) or None bbox = grid_bbox + + def _gridconvvalue(self, value): + if isinstance(value, (str, _tkinter.Tcl_Obj)): + try: + svalue = str(value) + if not svalue: + return None + elif '.' in svalue: + return getdouble(svalue) + else: + return getint(svalue) + except ValueError: + pass + return value + def _grid_configure(self, command, index, cnf, kw): """Internal function.""" if type(cnf) is StringType and not kw: @@ -1354,22 +1369,14 @@ for i in range(0, len(words), 2): key = words[i][1:] value = words[i+1] - if not value: - value = None - elif '.' in str(value): - value = getdouble(value) - else: - value = getint(value) - dict[key] = value + dict[key] = self._gridconvvalue(value) return dict res = self.tk.call( ('grid', command, self._w, index) + options) if len(options) == 1: - if not res: return None - # In Tk 7.5, -width can be a float - if '.' in res: return getdouble(res) - return getint(res) + return self._gridconvvalue(res) + def grid_columnconfigure(self, index, cnf={}, **kw): """Configure column INDEX of a grid. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,9 @@ Library ------- +- Issue #20635: Fixed grid_columnconfigure() and grid_rowconfigure() methods of + Tkinter widgets to work in wantobjects=True mode. + - Issue #17671: Fixed a crash when use non-initialized io.BufferedRWPair. Based on patch by Stephen Tu. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 17:35:48 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 19 Feb 2014 17:35:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogRml4ZWQgZ3JpZF9j?= =?utf-8?q?olumnconfigure=28=29_and_grid=5Frowconfigure=28=29_methods_of?= Message-ID: <3fTl101C8qz7Ljy@mail.python.org> http://hg.python.org/cpython/rev/6227b0ecb5fb changeset: 89272:6227b0ecb5fb branch: 3.3 parent: 89259:83013a7be836 user: Serhiy Storchaka date: Wed Feb 19 18:34:05 2014 +0200 summary: Fixed grid_columnconfigure() and grid_rowconfigure() methods of Tkinter widgets to work in wantobjects=True mode. files: Lib/tkinter/__init__.py | 29 ++++++++++++++++++----------- Misc/NEWS | 3 +++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -1339,6 +1339,21 @@ args = args + (col2, row2) return self._getints(self.tk.call(*args)) or None bbox = grid_bbox + + def _gridconvvalue(self, value): + if isinstance(value, (str, _tkinter.Tcl_Obj)): + try: + svalue = str(value) + if not svalue: + return None + elif '.' in svalue: + return getdouble(svalue) + else: + return getint(svalue) + except ValueError: + pass + return value + def _grid_configure(self, command, index, cnf, kw): """Internal function.""" if isinstance(cnf, str) and not kw: @@ -1357,22 +1372,14 @@ for i in range(0, len(words), 2): key = words[i][1:] value = words[i+1] - if not value: - value = None - elif '.' in str(value): - value = getdouble(value) - else: - value = getint(value) - dict[key] = value + dict[key] = self._gridconvvalue(value) return dict res = self.tk.call( ('grid', command, self._w, index) + options) if len(options) == 1: - if not res: return None - # In Tk 7.5, -width can be a float - if '.' in res: return getdouble(res) - return getint(res) + return self._gridconvvalue(res) + def grid_columnconfigure(self, index, cnf={}, **kw): """Configure column INDEX of a grid. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -20,6 +20,9 @@ Library ------- +- Issue #20635: Fixed grid_columnconfigure() and grid_rowconfigure() methods of + Tkinter widgets to work in wantobjects=True mode. + - Issue #19612: On Windows, subprocess.Popen.communicate() now ignores OSError(22, 'Invalid argument') when writing input data into stdin, whereas the process already exited. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 17:35:49 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 19 Feb 2014 17:35:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Fixed_grid=5Fcolumnconfigure=28=29_and_grid=5Frowconfigu?= =?utf-8?q?re=28=29_methods_of?= Message-ID: <3fTl113JThz7Lkb@mail.python.org> http://hg.python.org/cpython/rev/b6df5f8f86d3 changeset: 89273:b6df5f8f86d3 parent: 89270:186f6f56f4bc parent: 89272:6227b0ecb5fb user: Serhiy Storchaka date: Wed Feb 19 18:35:10 2014 +0200 summary: Fixed grid_columnconfigure() and grid_rowconfigure() methods of Tkinter widgets to work in wantobjects=True mode. files: Lib/tkinter/__init__.py | 29 ++++++++++++++++++----------- Misc/NEWS | 3 +++ 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -1339,6 +1339,21 @@ args = args + (col2, row2) return self._getints(self.tk.call(*args)) or None bbox = grid_bbox + + def _gridconvvalue(self, value): + if isinstance(value, (str, _tkinter.Tcl_Obj)): + try: + svalue = str(value) + if not svalue: + return None + elif '.' in svalue: + return getdouble(svalue) + else: + return getint(svalue) + except ValueError: + pass + return value + def _grid_configure(self, command, index, cnf, kw): """Internal function.""" if isinstance(cnf, str) and not kw: @@ -1357,22 +1372,14 @@ for i in range(0, len(words), 2): key = words[i][1:] value = words[i+1] - if not value: - value = None - elif '.' in str(value): - value = getdouble(value) - else: - value = getint(value) - dict[key] = value + dict[key] = self._gridconvvalue(value) return dict res = self.tk.call( ('grid', command, self._w, index) + options) if len(options) == 1: - if not res: return None - # In Tk 7.5, -width can be a float - if '.' in res: return getdouble(res) - return getint(res) + return self._gridconvvalue(res) + def grid_columnconfigure(self, index, cnf={}, **kw): """Configure column INDEX of a grid. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,9 @@ Library ------- +- Issue #20635: Fixed grid_columnconfigure() and grid_rowconfigure() methods of + Tkinter widgets to work in wantobjects=True mode. + - Issue #19612: On Windows, subprocess.Popen.communicate() now ignores OSError(22, 'Invalid argument') when writing input data into stdin, whereas the process already exited. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 17:46:32 2014 From: python-checkins at python.org (zach.ware) Date: Wed, 19 Feb 2014 17:46:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTEw?= =?utf-8?q?=3A_Confirm_that_the_code_attribute_of_the_SystemExit?= Message-ID: <3fTlFN0hKSz7LjR@mail.python.org> http://hg.python.org/cpython/rev/292cac3afca6 changeset: 89274:292cac3afca6 branch: 2.7 parent: 89271:857ddbaff14e user: Zachary Ware date: Wed Feb 19 10:43:13 2014 -0600 summary: Issue #20510: Confirm that the code attribute of the SystemExit exception raised by sys.exit is None when no code is given. As suggested by Serhiy Storchaka. files: Lib/test/test_sys.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -119,6 +119,10 @@ self.assertRaises(TypeError, sys.exit, 42, 42) # call without argument + with self.assertRaises(SystemExit) as cm: + sys.exit() + self.assertIsNone(cm.exception.code) + rc, out, err = assert_python_ok('-c', 'import sys; sys.exit()') self.assertEqual(rc, 0) self.assertEqual(out, b'') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 17:46:33 2014 From: python-checkins at python.org (zach.ware) Date: Wed, 19 Feb 2014 17:46:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTEw?= =?utf-8?q?=3A_Confirm_that_the_code_attribute_of_the_SystemExit?= Message-ID: <3fTlFP2kXxz7Ljl@mail.python.org> http://hg.python.org/cpython/rev/71411d5f3c8b changeset: 89275:71411d5f3c8b branch: 3.3 parent: 89272:6227b0ecb5fb user: Zachary Ware date: Wed Feb 19 10:44:47 2014 -0600 summary: Issue #20510: Confirm that the code attribute of the SystemExit exception raised by sys.exit is None when no code is given. As suggested by Serhiy Storchaka. files: Lib/test/test_sys.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -91,6 +91,10 @@ self.assertRaises(TypeError, sys.exit, 42, 42) # call without argument + with self.assertRaises(SystemExit) as cm: + sys.exit() + self.assertIsNone(cm.exception.code) + rc, out, err = assert_python_ok('-c', 'import sys; sys.exit()') self.assertEqual(rc, 0) self.assertEqual(out, b'') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 17:46:34 2014 From: python-checkins at python.org (zach.ware) Date: Wed, 19 Feb 2014 17:46:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320510=3A_Merge_with_3=2E3?= Message-ID: <3fTlFQ4xcjz7Ljr@mail.python.org> http://hg.python.org/cpython/rev/24412574fe24 changeset: 89276:24412574fe24 parent: 89273:b6df5f8f86d3 parent: 89275:71411d5f3c8b user: Zachary Ware date: Wed Feb 19 10:46:05 2014 -0600 summary: Issue #20510: Merge with 3.3 files: Lib/test/test_sys.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -94,6 +94,10 @@ self.assertRaises(TypeError, sys.exit, 42, 42) # call without argument + with self.assertRaises(SystemExit) as cm: + sys.exit() + self.assertIsNone(cm.exception.code) + rc, out, err = assert_python_ok('-c', 'import sys; sys.exit()') self.assertEqual(rc, 0) self.assertEqual(out, b'') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 18:04:59 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 19 Feb 2014 18:04:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNjcy?= =?utf-8?q?=3A_Fixed_tests_for_TarFile=2Elist=28=29_on_non-UTF-8_locales?= =?utf-8?q?=2E?= Message-ID: <3fTlfg0myXzSRW@mail.python.org> http://hg.python.org/cpython/rev/b508cbc29acf changeset: 89277:b508cbc29acf branch: 3.3 parent: 89272:6227b0ecb5fb user: Serhiy Storchaka date: Wed Feb 19 18:44:12 2014 +0200 summary: Issue #20672: Fixed tests for TarFile.list() on non-UTF-8 locales. files: Lib/test/test_tarfile.py | 18 ++++++++++-------- 1 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -238,14 +238,16 @@ self.assertIn(b'ustar/dirtype/', out) self.assertIn(b'ustar/dirtype-with-size/', out) # Make sure it is able to print unencodable characters - self.assertIn(br'ustar/umlauts-' - br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) - self.assertIn(br'misc/regtype-hpux-signed-chksum-' - br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) - self.assertIn(br'misc/regtype-old-v7-signed-chksum-' - br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) - self.assertIn(br'pax/bad-pax-\udce4\udcf6\udcfc', out) - self.assertIn(br'pax/hdrcharset-\udce4\udcf6\udcfc', out) + def conv(b): + s = b.decode(self.tar.encoding, 'surrogateescape') + return s.encode('ascii', 'backslashreplace') + self.assertIn(conv(b'ustar/umlauts-\xc4\xd6\xdc\xe4\xf6\xfc\xdf'), out) + self.assertIn(conv(b'misc/regtype-hpux-signed-chksum-' + b'\xc4\xd6\xdc\xe4\xf6\xfc\xdf'), out) + self.assertIn(conv(b'misc/regtype-old-v7-signed-chksum-' + b'\xc4\xd6\xdc\xe4\xf6\xfc\xdf'), out) + self.assertIn(conv(b'pax/bad-pax-\xe4\xf6\xfc'), out) + self.assertIn(conv(b'pax/hdrcharset-\xe4\xf6\xfc'), out) # Make sure it prints files separated by one newline without any # 'ls -l'-like accessories if verbose flag is not being used # ... -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 18:05:00 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 19 Feb 2014 18:05:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320672=3A_Fixed_tests_for_TarFile=2Elist=28=29_o?= =?utf-8?q?n_non-UTF-8_locales=2E?= Message-ID: <3fTlfh2BdkzSRW@mail.python.org> http://hg.python.org/cpython/rev/13d27bad7393 changeset: 89278:13d27bad7393 parent: 89273:b6df5f8f86d3 parent: 89277:b508cbc29acf user: Serhiy Storchaka date: Wed Feb 19 18:50:35 2014 +0200 summary: Issue #20672: Fixed tests for TarFile.list() on non-UTF-8 locales. files: Lib/test/test_tarfile.py | 18 ++++++++++-------- 1 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -240,14 +240,16 @@ self.assertIn(b'ustar/dirtype/', out) self.assertIn(b'ustar/dirtype-with-size/', out) # Make sure it is able to print unencodable characters - self.assertIn(br'ustar/umlauts-' - br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) - self.assertIn(br'misc/regtype-hpux-signed-chksum-' - br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) - self.assertIn(br'misc/regtype-old-v7-signed-chksum-' - br'\udcc4\udcd6\udcdc\udce4\udcf6\udcfc\udcdf', out) - self.assertIn(br'pax/bad-pax-\udce4\udcf6\udcfc', out) - self.assertIn(br'pax/hdrcharset-\udce4\udcf6\udcfc', out) + def conv(b): + s = b.decode(self.tar.encoding, 'surrogateescape') + return s.encode('ascii', 'backslashreplace') + self.assertIn(conv(b'ustar/umlauts-\xc4\xd6\xdc\xe4\xf6\xfc\xdf'), out) + self.assertIn(conv(b'misc/regtype-hpux-signed-chksum-' + b'\xc4\xd6\xdc\xe4\xf6\xfc\xdf'), out) + self.assertIn(conv(b'misc/regtype-old-v7-signed-chksum-' + b'\xc4\xd6\xdc\xe4\xf6\xfc\xdf'), out) + self.assertIn(conv(b'pax/bad-pax-\xe4\xf6\xfc'), out) + self.assertIn(conv(b'pax/hdrcharset-\xe4\xf6\xfc'), out) # Make sure it prints files separated by one newline without any # 'ls -l'-like accessories if verbose flag is not being used # ... -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 18:05:02 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 19 Feb 2014 18:05:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuMyk6?= =?utf-8?q?_Merge_heads?= Message-ID: <3fTlfk0qkcz7Ljd@mail.python.org> http://hg.python.org/cpython/rev/d89178781873 changeset: 89279:d89178781873 branch: 3.3 parent: 89277:b508cbc29acf parent: 89275:71411d5f3c8b user: Serhiy Storchaka date: Wed Feb 19 19:03:58 2014 +0200 summary: Merge heads files: Lib/test/test_sys.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -91,6 +91,10 @@ self.assertRaises(TypeError, sys.exit, 42, 42) # call without argument + with self.assertRaises(SystemExit) as cm: + sys.exit() + self.assertIsNone(cm.exception.code) + rc, out, err = assert_python_ok('-c', 'import sys; sys.exit()') self.assertEqual(rc, 0) self.assertEqual(out, b'') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 18:05:03 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 19 Feb 2014 18:05:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_heads?= Message-ID: <3fTlfl338Gz7LjR@mail.python.org> http://hg.python.org/cpython/rev/eec4e6ef1765 changeset: 89280:eec4e6ef1765 parent: 89278:13d27bad7393 parent: 89276:24412574fe24 user: Serhiy Storchaka date: Wed Feb 19 19:04:12 2014 +0200 summary: Merge heads files: Lib/test/test_sys.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -94,6 +94,10 @@ self.assertRaises(TypeError, sys.exit, 42, 42) # call without argument + with self.assertRaises(SystemExit) as cm: + sys.exit() + self.assertIsNone(cm.exception.code) + rc, out, err = assert_python_ok('-c', 'import sys; sys.exit()') self.assertEqual(rc, 0) self.assertEqual(out, b'') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 18:05:04 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 19 Feb 2014 18:05:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <3fTlfm4sYfz7Ljs@mail.python.org> http://hg.python.org/cpython/rev/87edfb145d84 changeset: 89281:87edfb145d84 parent: 89280:eec4e6ef1765 parent: 89279:d89178781873 user: Serhiy Storchaka date: Wed Feb 19 19:04:28 2014 +0200 summary: Null merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 18:10:49 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 19 Feb 2014 18:10:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320682=3A_Fix_UNIX?= =?utf-8?q?_sockets_tests_of_test=5Fasyncio_on_Mac_OS_X_Tiger?= Message-ID: <3fTlnP2GWFz7Ljv@mail.python.org> http://hg.python.org/cpython/rev/e6016fffc894 changeset: 89282:e6016fffc894 user: Victor Stinner date: Wed Feb 19 18:10:32 2014 +0100 summary: Close #20682: Fix UNIX sockets tests of test_asyncio on Mac OS X Tiger On Mac OS X Tiger (and older), getsockname() returns a zero-length address for UNIX socket, and so 'sockname' extra info is None. files: Lib/test/test_asyncio/test_events.py | 32 +++++++++++++-- 1 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -4,6 +4,7 @@ import gc import io import os +import platform import signal import socket try: @@ -40,6 +41,15 @@ raise FileNotFoundError(filename) +def osx_tiger(): + """Return True if the platform is Mac OS 10.4 or older.""" + if sys.platform != 'darwin': + return False + version = platform.mac_ver()[0] + version = tuple(map(int, version.split('.'))) + return version < (10, 5) + + ONLYCERT = data_file('ssl_cert.pem') ONLYKEY = data_file('ssl_key.pem') SIGNED_CERTFILE = data_file('keycert3.pem') @@ -499,10 +509,12 @@ self.loop.run_forever() self.assertEqual(caught, 1) - def _basetest_create_connection(self, connection_fut): + def _basetest_create_connection(self, connection_fut, check_sockname): tr, pr = self.loop.run_until_complete(connection_fut) self.assertIsInstance(tr, asyncio.Transport) self.assertIsInstance(pr, asyncio.Protocol) + if check_sockname: + self.assertIsNotNone(tr.get_extra_info('sockname')) self.loop.run_until_complete(pr.done) self.assertGreater(pr.nbytes, 0) tr.close() @@ -515,10 +527,14 @@ @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_create_unix_connection(self): + # Issue #20682: On Mac OS X Tiger, getsockname() returns a + # zero-length address for UNIX socket. + check_sockname = not osx_tiger() + with test_utils.run_test_unix_server() as httpd: conn_fut = self.loop.create_unix_connection( lambda: MyProto(loop=self.loop), httpd.address) - self._basetest_create_connection(conn_fut) + self._basetest_create_connection(conn_fut, check_sockname) def test_create_connection_sock(self): with test_utils.run_test_server() as httpd: @@ -548,12 +564,14 @@ self.assertGreater(pr.nbytes, 0) tr.close() - def _basetest_create_ssl_connection(self, connection_fut): + def _basetest_create_ssl_connection(self, connection_fut, + check_sockname=True): tr, pr = self.loop.run_until_complete(connection_fut) self.assertIsInstance(tr, asyncio.Transport) self.assertIsInstance(pr, asyncio.Protocol) self.assertTrue('ssl' in tr.__class__.__name__.lower()) - self.assertIsNotNone(tr.get_extra_info('sockname')) + if check_sockname: + self.assertIsNotNone(tr.get_extra_info('sockname')) self.loop.run_until_complete(pr.done) self.assertGreater(pr.nbytes, 0) tr.close() @@ -571,6 +589,10 @@ @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets') def test_create_ssl_unix_connection(self): + # Issue #20682: On Mac OS X Tiger, getsockname() returns a + # zero-length address for UNIX socket. + check_sockname = not osx_tiger() + with test_utils.run_test_unix_server(use_ssl=True) as httpd: conn_fut = self.loop.create_unix_connection( lambda: MyProto(loop=self.loop), @@ -578,7 +600,7 @@ ssl=test_utils.dummy_ssl_context(), server_hostname='127.0.0.1') - self._basetest_create_ssl_connection(conn_fut) + self._basetest_create_ssl_connection(conn_fut, check_sockname) def test_create_connection_local_addr(self): with test_utils.run_test_server() as httpd: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 18:32:14 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 19 Feb 2014 18:32:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320682=3A_Oops=2C_?= =?utf-8?q?fix_test=5Fcreate=5Fconnection=28=29_of_test=5Fasyncio_=28fix_m?= =?utf-8?q?y?= Message-ID: <3fTmG64T9Wz7LjS@mail.python.org> http://hg.python.org/cpython/rev/07cdce316b1d changeset: 89283:07cdce316b1d user: Victor Stinner date: Wed Feb 19 18:32:03 2014 +0100 summary: Issue #20682: Oops, fix test_create_connection() of test_asyncio (fix my previous commit) files: Lib/test/test_asyncio/test_events.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -509,7 +509,7 @@ self.loop.run_forever() self.assertEqual(caught, 1) - def _basetest_create_connection(self, connection_fut, check_sockname): + def _basetest_create_connection(self, connection_fut, check_sockname=True): tr, pr = self.loop.run_until_complete(connection_fut) self.assertIsInstance(tr, asyncio.Transport) self.assertIsInstance(pr, asyncio.Protocol) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 22:05:34 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 19 Feb 2014 22:05:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320654=3A_Fixed_py?= =?utf-8?q?doc_for_enums_with_zero_value=2E__Patch_by_Vajrasky_Kok=2E?= Message-ID: <3fTs0G5KyRz7Lk3@mail.python.org> http://hg.python.org/cpython/rev/8a3e896f0681 changeset: 89284:8a3e896f0681 user: Serhiy Storchaka date: Wed Feb 19 23:05:12 2014 +0200 summary: Issue #20654: Fixed pydoc for enums with zero value. Patch by Vajrasky Kok. files: Lib/pydoc.py | 9 ++++++--- Lib/test/test_pydoc.py | 10 ++++++++++ Misc/NEWS | 2 ++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1244,9 +1244,12 @@ doc = getdoc(value) else: doc = None - push(self.docother( - getattr(object, name, None) or homecls.__dict__[name], - name, mod, maxlen=70, doc=doc) + '\n') + try: + obj = getattr(object, name) + except AttributeError: + obj = homecls.__dict__[name] + push(self.docother(obj, name, mod, maxlen=70, doc=doc) + + '\n') return attrs attrs = [(name, kind, cls, value) diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -386,6 +386,16 @@ print_diffs(expected_text, result) self.fail("outputs are not equal, see diff above") + def test_text_enum_member_with_value_zero(self): + # Test issue #20654 to ensure enum member with value 0 can be + # displayed. It used to throw KeyError: 'zero'. + import enum + class BinaryInteger(enum.IntEnum): + zero = 0 + one = 1 + doc = pydoc.render_doc(BinaryInteger) + self.assertIn('', doc) + def test_issue8225(self): # Test issue8225 to ensure no doc link appears for xml.etree result, doc_loc = get_pydoc_text(xml.etree) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,8 @@ Library ------- +- Issue #20654: Fixed pydoc for enums with zero value. Patch by Vajrasky Kok. + - Issue #20635: Fixed grid_columnconfigure() and grid_rowconfigure() methods of Tkinter widgets to work in wantobjects=True mode. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 22:28:04 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 19 Feb 2014 22:28:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzY4MTU6?= =?utf-8?q?_os=2Epath=2Eexpandvars=28=29_now_supports_non-ASCII_Unicode_en?= =?utf-8?q?vironment?= Message-ID: <3fTsVD1yxzz7LjT@mail.python.org> http://hg.python.org/cpython/rev/d11ca14c9a61 changeset: 89285:d11ca14c9a61 branch: 2.7 parent: 89274:292cac3afca6 user: Serhiy Storchaka date: Wed Feb 19 23:27:37 2014 +0200 summary: Issue #6815: os.path.expandvars() now supports non-ASCII Unicode environment variables names and values. files: Lib/ntpath.py | 25 ++++++++---- Lib/posixpath.py | 27 ++++++++++--- Lib/test/test_genericpath.py | 29 ++++++++++++++- Lib/test/test_ntpath.py | 36 ++++++++++++++++-- Lib/test/test_support.py | 46 ++++++++++++++++++++++++ Misc/NEWS | 3 + 6 files changed, 145 insertions(+), 21 deletions(-) diff --git a/Lib/ntpath.py b/Lib/ntpath.py --- a/Lib/ntpath.py +++ b/Lib/ntpath.py @@ -294,6 +294,13 @@ return path import string varchars = string.ascii_letters + string.digits + '_-' + if isinstance(path, unicode): + encoding = sys.getfilesystemencoding() + def getenv(var): + return os.environ[var.encode(encoding)].decode(encoding) + else: + def getenv(var): + return os.environ[var] res = '' index = 0 pathlen = len(path) @@ -322,9 +329,9 @@ index = pathlen - 1 else: var = path[:index] - if var in os.environ: - res = res + os.environ[var] - else: + try: + res = res + getenv(var) + except KeyError: res = res + '%' + var + '%' elif c == '$': # variable or '$$' if path[index + 1:index + 2] == '$': @@ -336,9 +343,9 @@ try: index = path.index('}') var = path[:index] - if var in os.environ: - res = res + os.environ[var] - else: + try: + res = res + getenv(var) + except KeyError: res = res + '${' + var + '}' except ValueError: res = res + '${' + path @@ -351,9 +358,9 @@ var = var + c index = index + 1 c = path[index:index + 1] - if var in os.environ: - res = res + os.environ[var] - else: + try: + res = res + getenv(var) + except KeyError: res = res + '$' + var if c != '': index = index - 1 diff --git a/Lib/posixpath.py b/Lib/posixpath.py --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -285,28 +285,43 @@ # Non-existent variables are left unchanged. _varprog = None +_uvarprog = None def expandvars(path): """Expand shell variables of form $var and ${var}. Unknown variables are left unchanged.""" - global _varprog + global _varprog, _uvarprog if '$' not in path: return path - if not _varprog: - import re - _varprog = re.compile(r'\$(\w+|\{[^}]*\})') + if isinstance(path, _unicode): + if not _varprog: + import re + _varprog = re.compile(r'\$(\w+|\{[^}]*\})') + varprog = _varprog + encoding = sys.getfilesystemencoding() + else: + if not _uvarprog: + import re + _uvarprog = re.compile(_unicode(r'\$(\w+|\{[^}]*\})'), re.UNICODE) + varprog = _uvarprog + encoding = None i = 0 while True: - m = _varprog.search(path, i) + m = varprog.search(path, i) if not m: break i, j = m.span(0) name = m.group(1) if name.startswith('{') and name.endswith('}'): name = name[1:-1] + if encoding: + name = name.encode(encoding) if name in os.environ: tail = path[j:] - path = path[:i] + os.environ[name] + value = os.environ[name] + if encoding: + value = value.decode(encoding) + path = path[:i] + value i = len(path) path += tail else: diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -199,13 +199,40 @@ self.assertEqual(expandvars("$[foo]bar"), "$[foo]bar") self.assertEqual(expandvars("$bar bar"), "$bar bar") self.assertEqual(expandvars("$?bar"), "$?bar") - self.assertEqual(expandvars("${foo}bar"), "barbar") self.assertEqual(expandvars("$foo}bar"), "bar}bar") self.assertEqual(expandvars("${foo"), "${foo") self.assertEqual(expandvars("${{foo}}"), "baz1}") self.assertEqual(expandvars("$foo$foo"), "barbar") self.assertEqual(expandvars("$bar$bar"), "$bar$bar") + @unittest.skipUnless(test_support.FS_NONASCII, 'need test_support.FS_NONASCII') + def test_expandvars_nonascii(self): + if self.pathmodule.__name__ == 'macpath': + self.skipTest('macpath.expandvars is a stub') + expandvars = self.pathmodule.expandvars + def check(value, expected): + self.assertEqual(expandvars(value), expected) + encoding = sys.getfilesystemencoding() + with test_support.EnvironmentVarGuard() as env: + env.clear() + unonascii = test_support.FS_NONASCII + snonascii = unonascii.encode(encoding) + env['spam'] = snonascii + env[snonascii] = 'ham' + snonascii + check(snonascii, snonascii) + check('$spam bar', '%s bar' % snonascii) + check('${spam}bar', '%sbar' % snonascii) + check('${%s}bar' % snonascii, 'ham%sbar' % snonascii) + check('$bar%s bar' % snonascii, '$bar%s bar' % snonascii) + check('$spam}bar', '%s}bar' % snonascii) + + check(unonascii, unonascii) + check(u'$spam bar', u'%s bar' % unonascii) + check(u'${spam}bar', u'%sbar' % unonascii) + check(u'${%s}bar' % unonascii, u'ham%sbar' % unonascii) + check(u'$bar%s bar' % unonascii, u'$bar%s bar' % unonascii) + check(u'$spam}bar', u'%s}bar' % unonascii) + def test_abspath(self): self.assertIn("foo", self.pathmodule.abspath("foo")) diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -1,16 +1,19 @@ import ntpath import os +import sys from test.test_support import TestFailed from test import test_support, test_genericpath import unittest +def tester0(fn, wantResult): + gotResult = eval(fn) + if wantResult != gotResult: + raise TestFailed, "%s should return: %r but returned: %r" \ + %(fn, wantResult, gotResult) def tester(fn, wantResult): fn = fn.replace("\\", "\\\\") - gotResult = eval(fn) - if wantResult != gotResult: - raise TestFailed, "%s should return: %s but returned: %s" \ - %(str(fn), str(wantResult), str(gotResult)) + tester0(fn, wantResult) class TestNtpath(unittest.TestCase): @@ -173,7 +176,6 @@ tester('ntpath.expandvars("$[foo]bar")', "$[foo]bar") tester('ntpath.expandvars("$bar bar")', "$bar bar") tester('ntpath.expandvars("$?bar")', "$?bar") - tester('ntpath.expandvars("${foo}bar")', "barbar") tester('ntpath.expandvars("$foo}bar")', "bar}bar") tester('ntpath.expandvars("${foo")', "${foo") tester('ntpath.expandvars("${{foo}}")', "baz1}") @@ -187,6 +189,30 @@ tester('ntpath.expandvars("%foo%%bar")', "bar%bar") tester('ntpath.expandvars("\'%foo%\'%bar")', "\'%foo%\'%bar") + @unittest.skipUnless(test_support.FS_NONASCII, 'need test_support.FS_NONASCII') + def test_expandvars_nonascii(self): + encoding = sys.getfilesystemencoding() + def check(value, expected): + tester0("ntpath.expandvars(%r)" % value, expected) + tester0("ntpath.expandvars(%r)" % value.decode(encoding), + expected.decode(encoding)) + with test_support.EnvironmentVarGuard() as env: + env.clear() + unonascii = test_support.FS_NONASCII + snonascii = unonascii.encode(encoding) + env['spam'] = snonascii + env[snonascii] = 'ham' + snonascii + check('$spam bar', '%s bar' % snonascii) + check('$%s bar' % snonascii, '$%s bar' % snonascii) + check('${spam}bar', '%sbar' % snonascii) + check('${%s}bar' % snonascii, 'ham%sbar' % snonascii) + check('$spam}bar', '%s}bar' % snonascii) + check('$%s}bar' % snonascii, '$%s}bar' % snonascii) + check('%spam% bar', '%s bar' % snonascii) + check('%{}% bar'.format(snonascii), 'ham%s bar' % snonascii) + check('%spam%bar', '%sbar' % snonascii) + check('%{}%bar'.format(snonascii), 'ham%sbar' % snonascii) + def test_abspath(self): # ntpath.abspath() can only be used on a system with the "nt" module # (reasonably), so we protect this test with "import nt". This allows diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -465,6 +465,52 @@ is_jython = sys.platform.startswith('java') +# FS_NONASCII: non-ASCII Unicode character encodable by +# sys.getfilesystemencoding(), or None if there is no such character. +FS_NONASCII = None +if have_unicode: + for character in ( + # First try printable and common characters to have a readable filename. + # For each character, the encoding list are just example of encodings able + # to encode the character (the list is not exhaustive). + + # U+00E6 (Latin Small Letter Ae): cp1252, iso-8859-1 + unichr(0x00E6), + # U+0130 (Latin Capital Letter I With Dot Above): cp1254, iso8859_3 + unichr(0x0130), + # U+0141 (Latin Capital Letter L With Stroke): cp1250, cp1257 + unichr(0x0141), + # U+03C6 (Greek Small Letter Phi): cp1253 + unichr(0x03C6), + # U+041A (Cyrillic Capital Letter Ka): cp1251 + unichr(0x041A), + # U+05D0 (Hebrew Letter Alef): Encodable to cp424 + unichr(0x05D0), + # U+060C (Arabic Comma): cp864, cp1006, iso8859_6, mac_arabic + unichr(0x060C), + # U+062A (Arabic Letter Teh): cp720 + unichr(0x062A), + # U+0E01 (Thai Character Ko Kai): cp874 + unichr(0x0E01), + + # Then try more "special" characters. "special" because they may be + # interpreted or displayed differently depending on the exact locale + # encoding and the font. + + # U+00A0 (No-Break Space) + unichr(0x00A0), + # U+20AC (Euro Sign) + unichr(0x20AC), + ): + try: + character.encode(sys.getfilesystemencoding())\ + .decode(sys.getfilesystemencoding()) + except UnicodeError: + pass + else: + FS_NONASCII = character + break + # Filename used for testing if os.name == 'java': # Jython disallows @ in module names diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -39,6 +39,9 @@ Library ------- +- Issue #6815: os.path.expandvars() now supports non-ASCII Unicode environment + variables names and values. + - Issue #20635: Fixed grid_columnconfigure() and grid_rowconfigure() methods of Tkinter widgets to work in wantobjects=True mode. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 22:28:55 2014 From: python-checkins at python.org (yury.selivanov) Date: Wed, 19 Feb 2014 22:28:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=3A_Fix_getfullargs?= =?utf-8?q?pec=28=29_to_not_to_follow_=5F=5Fwrapped=5F=5F_chains?= Message-ID: <3fTsWC0BLDz7Ljb@mail.python.org> http://hg.python.org/cpython/rev/65fb95578f94 changeset: 89286:65fb95578f94 parent: 89283:07cdce316b1d user: Yury Selivanov date: Wed Feb 19 16:27:23 2014 -0500 summary: inspect: Fix getfullargspec() to not to follow __wrapped__ chains Initial patch by Nick Coghlan. files: Lib/inspect.py | 115 +++++++++++++++----------- Lib/test/test_inspect.py | 40 +++++++++ Misc/NEWS | 4 + 3 files changed, 111 insertions(+), 48 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -949,9 +949,9 @@ The first four items in the tuple correspond to getargspec(). """ - builtin_method_param = None - - if ismethod(func): + try: + # Re: `skip_bound_arg=False` + # # There is a notable difference in behaviour between getfullargspec # and Signature: the former always returns 'self' parameter for bound # methods, whereas the Signature always shows the actual calling @@ -960,20 +960,15 @@ # To simulate this behaviour, we "unbind" bound methods, to trick # inspect.signature to always return their first parameter ("self", # usually) - func = func.__func__ - - elif isbuiltin(func): - # We have a builtin function or method. For that, we check the - # special '__text_signature__' attribute, provided by the - # Argument Clinic. If it's a method, we'll need to make sure - # that its first parameter (usually "self") is always returned - # (see the previous comment). - text_signature = getattr(func, '__text_signature__', None) - if text_signature and text_signature.startswith('($'): - builtin_method_param = _signature_get_bound_param(text_signature) - - try: - sig = signature(func) + + # Re: `follow_wrapper_chains=False` + # + # getfullargspec() historically ignored __wrapped__ attributes, + # so we ensure that remains the case in 3.3+ + + sig = _signature_internal(func, + follow_wrapper_chains=False, + skip_bound_arg=False) except Exception as ex: # Most of the times 'signature' will raise ValueError. # But, it can also raise AttributeError, and, maybe something @@ -1023,13 +1018,6 @@ # compatibility with 'func.__defaults__' defaults = None - if builtin_method_param and (not args or args[0] != builtin_method_param): - # `func` is a method, and we always need to return its - # first parameter -- usually "self" (to be backwards - # compatible with the previous implementation of - # getfullargspec) - args.insert(0, builtin_method_param) - return FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwdefaults, annotations) @@ -1719,7 +1707,7 @@ return clean_signature, self_parameter, last_positional_only -def _signature_fromstr(cls, obj, s): +def _signature_fromstr(cls, obj, s, skip_bound_arg=True): # Internal helper to parse content of '__text_signature__' # and return a Signature based on it Parameter = cls._parameter_cls @@ -1840,7 +1828,7 @@ if self_parameter is not None: assert parameters - if getattr(obj, '__self__', None): + if getattr(obj, '__self__', None) and skip_bound_arg: # strip off self, it's already been bound parameters.pop(0) else: @@ -1851,8 +1839,21 @@ return cls(parameters, return_annotation=cls.empty) -def signature(obj): - '''Get a signature object for the passed callable.''' +def _signature_from_builtin(cls, func, skip_bound_arg=True): + # Internal helper function to get signature for + # builtin callables + if not _signature_is_builtin(func): + raise TypeError("{!r} is not a Python builtin " + "function".format(func)) + + s = getattr(func, "__text_signature__", None) + if not s: + raise ValueError("no signature found for builtin {!r}".format(func)) + + return _signature_fromstr(cls, func, s, skip_bound_arg) + + +def _signature_internal(obj, follow_wrapper_chains=True, skip_bound_arg=True): if not callable(obj): raise TypeError('{!r} is not a callable object'.format(obj)) @@ -1860,11 +1861,17 @@ if isinstance(obj, types.MethodType): # In this case we skip the first parameter of the underlying # function (usually `self` or `cls`). - sig = signature(obj.__func__) - return _signature_bound_method(sig) + sig = _signature_internal(obj.__func__, + follow_wrapper_chains, + skip_bound_arg) + if skip_bound_arg: + return _signature_bound_method(sig) + else: + return sig # Was this function wrapped by a decorator? - obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__"))) + if follow_wrapper_chains: + obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__"))) try: sig = obj.__signature__ @@ -1887,7 +1894,9 @@ # (usually `self`, or `cls`) will not be passed # automatically (as for boundmethods) - wrapped_sig = signature(partialmethod.func) + wrapped_sig = _signature_internal(partialmethod.func, + follow_wrapper_chains, + skip_bound_arg) sig = _signature_get_partial(wrapped_sig, partialmethod, (None,)) first_wrapped_param = tuple(wrapped_sig.parameters.values())[0] @@ -1896,7 +1905,8 @@ return sig.replace(parameters=new_params) if _signature_is_builtin(obj): - return Signature.from_builtin(obj) + return _signature_from_builtin(Signature, obj, + skip_bound_arg=skip_bound_arg) if isfunction(obj) or _signature_is_functionlike(obj): # If it's a pure Python function, or an object that is duck type @@ -1904,7 +1914,9 @@ return Signature.from_function(obj) if isinstance(obj, functools.partial): - wrapped_sig = signature(obj.func) + wrapped_sig = _signature_internal(obj.func, + follow_wrapper_chains, + skip_bound_arg) return _signature_get_partial(wrapped_sig, obj) sig = None @@ -1915,17 +1927,23 @@ # in its metaclass call = _signature_get_user_defined_method(type(obj), '__call__') if call is not None: - sig = signature(call) + sig = _signature_internal(call, + follow_wrapper_chains, + skip_bound_arg) else: # Now we check if the 'obj' class has a '__new__' method new = _signature_get_user_defined_method(obj, '__new__') if new is not None: - sig = signature(new) + sig = _signature_internal(new, + follow_wrapper_chains, + skip_bound_arg) else: # Finally, we should have at least __init__ implemented init = _signature_get_user_defined_method(obj, '__init__') if init is not None: - sig = signature(init) + sig = _signature_internal(init, + follow_wrapper_chains, + skip_bound_arg) if sig is None: # At this point we know, that `obj` is a class, with no user- @@ -1967,7 +1985,9 @@ call = _signature_get_user_defined_method(type(obj), '__call__') if call is not None: try: - sig = signature(call) + sig = _signature_internal(call, + follow_wrapper_chains, + skip_bound_arg) except ValueError as ex: msg = 'no signature found for {!r}'.format(obj) raise ValueError(msg) from ex @@ -1975,7 +1995,10 @@ if sig is not None: # For classes and objects we skip the first parameter of their # __call__, __new__, or __init__ methods - return _signature_bound_method(sig) + if skip_bound_arg: + return _signature_bound_method(sig) + else: + return sig if isinstance(obj, types.BuiltinFunctionType): # Raise a nicer error message for builtins @@ -1984,6 +2007,10 @@ raise ValueError('callable {!r} is not supported by signature'.format(obj)) +def signature(obj): + '''Get a signature object for the passed callable.''' + return _signature_internal(obj) + class _void: '''A private marker - used in Parameter & Signature''' @@ -2417,15 +2444,7 @@ @classmethod def from_builtin(cls, func): - if not _signature_is_builtin(func): - raise TypeError("{!r} is not a Python builtin " - "function".format(func)) - - s = getattr(func, "__text_signature__", None) - if not s: - raise ValueError("no signature found for builtin {!r}".format(func)) - - return _signature_fromstr(cls, func, s) + return _signature_from_builtin(cls, func) @property def parameters(self): diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -577,6 +577,46 @@ kwonlyargs_e=['arg'], formatted='(*, arg)') + def test_argspec_api_ignores_wrapped(self): + # Issue 20684: low level introspection API must ignore __wrapped__ + @functools.wraps(mod.spam) + def ham(x, y): + pass + # Basic check + self.assertArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)') + self.assertFullArgSpecEquals(ham, ['x', 'y'], formatted='(x, y)') + self.assertFullArgSpecEquals(functools.partial(ham), + ['x', 'y'], formatted='(x, y)') + # Other variants + def check_method(f): + self.assertArgSpecEquals(f, ['self', 'x', 'y'], + formatted='(self, x, y)') + class C: + @functools.wraps(mod.spam) + def ham(self, x, y): + pass + pham = functools.partialmethod(ham) + @functools.wraps(mod.spam) + def __call__(self, x, y): + pass + check_method(C()) + check_method(C.ham) + check_method(C().ham) + check_method(C.pham) + check_method(C().pham) + + class C_new: + @functools.wraps(mod.spam) + def __new__(self, x, y): + pass + check_method(C_new) + + class C_init: + @functools.wraps(mod.spam) + def __init__(self, x, y): + pass + check_method(C_init) + def test_getfullargspec_signature_attr(self): def test(): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,10 @@ loop.set_exception_handler(), loop.default_exception_handler(), and loop.call_exception_handler(). +- Issue #20684: Fix inspect.getfullargspec() to not to follow __wrapped__ + chains. Make its behaviour consistent with bound methods first argument. + Patch by Nick Coghlan and Yury Selivanov. + Tests ----- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 22:28:56 2014 From: python-checkins at python.org (yury.selivanov) Date: Wed, 19 Feb 2014 22:28:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge_heads?= Message-ID: <3fTsWD2CGjz7Ljy@mail.python.org> http://hg.python.org/cpython/rev/a673512bb81c changeset: 89287:a673512bb81c parent: 89286:65fb95578f94 parent: 89284:8a3e896f0681 user: Yury Selivanov date: Wed Feb 19 16:28:36 2014 -0500 summary: merge heads files: Lib/pydoc.py | 9 ++++++--- Lib/test/test_pydoc.py | 10 ++++++++++ Misc/NEWS | 2 ++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1244,9 +1244,12 @@ doc = getdoc(value) else: doc = None - push(self.docother( - getattr(object, name, None) or homecls.__dict__[name], - name, mod, maxlen=70, doc=doc) + '\n') + try: + obj = getattr(object, name) + except AttributeError: + obj = homecls.__dict__[name] + push(self.docother(obj, name, mod, maxlen=70, doc=doc) + + '\n') return attrs attrs = [(name, kind, cls, value) diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -386,6 +386,16 @@ print_diffs(expected_text, result) self.fail("outputs are not equal, see diff above") + def test_text_enum_member_with_value_zero(self): + # Test issue #20654 to ensure enum member with value 0 can be + # displayed. It used to throw KeyError: 'zero'. + import enum + class BinaryInteger(enum.IntEnum): + zero = 0 + one = 1 + doc = pydoc.render_doc(BinaryInteger) + self.assertIn('', doc) + def test_issue8225(self): # Test issue8225 to ensure no doc link appears for xml.etree result, doc_loc = get_pydoc_text(xml.etree) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,8 @@ Library ------- +- Issue #20654: Fixed pydoc for enums with zero value. Patch by Vajrasky Kok. + - Issue #20635: Fixed grid_columnconfigure() and grid_rowconfigure() methods of Tkinter widgets to work in wantobjects=True mode. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 19 23:17:48 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 19 Feb 2014 23:17:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2C_Tulip_issue_=23?= =?utf-8?q?136=3A_Add_get/set=5Fdebug=28=29_methods_to_BaseEventLoopTests?= =?utf-8?q?=2E?= Message-ID: <3fTtbc4Hc9z7LjS@mail.python.org> http://hg.python.org/cpython/rev/dbf13a7d3987 changeset: 89288:dbf13a7d3987 user: Victor Stinner date: Wed Feb 19 23:15:02 2014 +0100 summary: asyncio, Tulip issue #136: Add get/set_debug() methods to BaseEventLoopTests. Add also a PYTHONASYNCIODEBUG environment variable to debug coroutines since Python startup, to be able to debug coroutines defined directly in the asyncio module. files: Doc/library/asyncio-dev.rst | 10 ++- Doc/library/asyncio-eventloop.rst | 16 ++++++ Doc/using/cmdline.rst | 8 +++ Lib/asyncio/base_events.py | 7 ++ Lib/asyncio/events.py | 8 +++ Lib/asyncio/tasks.py | 5 +- Lib/test/test_asyncio/test_base_events.py | 6 ++ Lib/test/test_asyncio/test_tasks.py | 28 +++++++++++ 8 files changed, 83 insertions(+), 5 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -1,5 +1,7 @@ .. currentmodule:: asyncio +.. _asyncio-dev: + Develop with asyncio ==================== @@ -81,10 +83,10 @@ When a coroutine function is called but not passed to :func:`async` or to the :class:`Task` constructor, it is not scheduled and it is probably a bug. -To detect such bug, set :data:`asyncio.tasks._DEBUG` to ``True``. When the -coroutine object is destroyed by the garbage collector, a log will be emitted -with the traceback where the coroutine function was called. See the -:ref:`asyncio logger `. +To detect such bug, set the environment variable :envvar:`PYTHONASYNCIODEBUG` +to ``1``. When the coroutine object is destroyed by the garbage collector, a +log will be emitted with the traceback where the coroutine function was called. +See the :ref:`asyncio logger `. The debug flag changes the behaviour of the :func:`coroutine` decorator. The debug flag value is only used when then coroutine function is defined, not when diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -553,6 +553,22 @@ Set the default executor used by :meth:`run_in_executor`. +Debug mode +---------- + +.. method:: BaseEventLoop.get_debug() + + Get the debug mode (:class:`bool`) of the event loop. + +.. method:: BaseEventLoop.set_debug(enabled: bool) + + Set the debug mode of the event loop. + +.. seealso:: + + The :ref:`Develop with asyncio ` section. + + Server ------ diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -614,6 +614,14 @@ .. versionadded:: 3.4 +.. envvar:: PYTHONASYNCIODEBUG + + If this environment variable is set to a non-empty string, enable the debug + mode of the :mod:`asyncio` module. + + .. versionadded:: 3.4 + + Debug-mode variables ~~~~~~~~~~~~~~~~~~~~ diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -123,6 +123,7 @@ self._running = False self._clock_resolution = time.get_clock_info('monotonic').resolution self._exception_handler = None + self._debug = False def _make_socket_transport(self, sock, protocol, waiter=None, *, extra=None, server=None): @@ -795,3 +796,9 @@ if not handle._cancelled: handle._run() handle = None # Needed to break cycles when an exception occurs. + + def get_debug(self): + return self._debug + + def set_debug(self, enabled): + self._debug = enabled diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -345,6 +345,14 @@ def call_exception_handler(self, context): raise NotImplementedError + # Debug flag management. + + def get_debug(self): + raise NotImplementedError + + def set_debug(self, enabled): + raise NotImplementedError + class AbstractEventLoopPolicy: """Abstract policy for accessing the event loop.""" diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -12,6 +12,8 @@ import functools import inspect import linecache +import os +import sys import traceback import weakref @@ -28,7 +30,8 @@ # 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. -_DEBUG = False +_DEBUG = (not sys.flags.ignore_environment + and bool(os.environ.get('PYTHONASYNCIODEBUG'))) class CoroWrapper: diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -197,6 +197,12 @@ self.assertEqual([h2], self.loop._scheduled) self.assertTrue(self.loop._process_events.called) + def test_set_debug(self): + self.loop.set_debug(True) + self.assertTrue(self.loop.get_debug()) + self.loop.set_debug(False) + self.assertFalse(self.loop.get_debug()) + @unittest.mock.patch('asyncio.base_events.time') @unittest.mock.patch('asyncio.base_events.logger') def test__run_once_logging(self, m_logger, m_time): diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1,7 +1,9 @@ """Tests for tasks.py.""" import gc +import os.path import unittest +from test.script_helper import assert_python_ok import asyncio from asyncio import test_utils @@ -1461,6 +1463,32 @@ cb.assert_called_once_with(fut) self.assertEqual(fut.result(), [3, 1, exc, exc2]) + def test_env_var_debug(self): + path = os.path.dirname(asyncio.__file__) + path = os.path.normpath(os.path.join(path, '..')) + code = '\n'.join(( + 'import sys', + 'sys.path.insert(0, %r)' % path, + 'import asyncio.tasks', + 'print(asyncio.tasks._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) + self.assertEqual(stdout.rstrip(), b'False') + + sts, stdout, stderr = assert_python_ok('-c', code, + PYTHONASYNCIODEBUG='') + self.assertEqual(stdout.rstrip(), b'False') + + sts, stdout, stderr = assert_python_ok('-c', code, + PYTHONASYNCIODEBUG='1') + self.assertEqual(stdout.rstrip(), b'True') + + sts, stdout, stderr = assert_python_ok('-E', '-c', code, + PYTHONASYNCIODEBUG='1') + self.assertEqual(stdout.rstrip(), b'False') + class FutureGatherTests(GatherTestsBase, unittest.TestCase): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 00:07:19 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 20 Feb 2014 00:07:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_update_magic_number_for_?= =?utf-8?q?=2320625?= Message-ID: <3fTvhl3KsKz7LjR@mail.python.org> http://hg.python.org/cpython/rev/e301a515f8f4 changeset: 89289:e301a515f8f4 user: Benjamin Peterson date: Wed Feb 19 18:05:36 2014 -0500 summary: update magic number for #20625 files: Lib/importlib/_bootstrap.py | 3 +- Python/importlib.h | 320 ++++++++++++------------ 2 files changed, 162 insertions(+), 161 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -418,12 +418,13 @@ # Python 3.4a1 3280 (remove implicit class argument) # Python 3.4a4 3290 (changes to __qualname__ computation) # Python 3.4a4 3300 (more changes to __qualname__ computation) +# Python 3.4rc2 3310 (alter __qualname__ computation) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually # due to the addition of new opcodes). -MAGIC_NUMBER = (3300).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3310).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 01:45:26 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 20 Feb 2014 01:45:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_remove_refe?= =?utf-8?q?rence_to_=5FDEBUG_=28now_replaced_with_PYTHONASYNCIODEBUG?= Message-ID: <3fTxsy5r66z7Ljl@mail.python.org> http://hg.python.org/cpython/rev/549f451aa4c3 changeset: 89290:549f451aa4c3 user: Victor Stinner date: Thu Feb 20 01:44:10 2014 +0100 summary: asyncio doc: remove reference to _DEBUG (now replaced with PYTHONASYNCIODEBUG env var), document the default debug mode files: Doc/library/asyncio-dev.rst | 1 - Doc/library/asyncio-eventloop.rst | 2 +- 2 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -98,7 +98,6 @@ Example with the bug:: import asyncio - asyncio.tasks._DEBUG = True @asyncio.coroutine def test(): diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -558,7 +558,7 @@ .. method:: BaseEventLoop.get_debug() - Get the debug mode (:class:`bool`) of the event loop. + Get the debug mode (:class:`bool`) of the event loop, ``False`` by default. .. method:: BaseEventLoop.set_debug(enabled: bool) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 02:59:56 2014 From: python-checkins at python.org (yury.selivanov) Date: Thu, 20 Feb 2014 02:59:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Edocs=3A_Document?= =?utf-8?q?_Error_Handling_API_and_asyncio=2EHandle?= Message-ID: <3fTzWw5BVwz7Ljd@mail.python.org> http://hg.python.org/cpython/rev/58fd64e55b29 changeset: 89291:58fd64e55b29 user: Yury Selivanov date: Wed Feb 19 20:58:44 2014 -0500 summary: asyncio.docs: Document Error Handling API and asyncio.Handle files: Doc/library/asyncio-eventloop.rst | 69 ++++++++++++++++++- 1 files changed, 67 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -142,6 +142,8 @@ Any positional arguments after the callback will be passed to the callback when it is called. + An instance of :class:`asyncio.Handle` is returned. + .. method:: BaseEventLoop.call_soon_threadsafe(callback, \*args) Like :meth:`call_soon`, but thread safe. @@ -167,8 +169,7 @@ Arrange for the *callback* to be called after the given *delay* seconds (either an int or float). - A "handle" is returned: an opaque object with a :meth:`cancel` method - that can be used to cancel the call. + An instance of :class:`asyncio.Handle` is returned. *callback* will be called exactly once per call to :meth:`call_later`. If two callbacks are scheduled for exactly the same time, it is @@ -553,6 +554,56 @@ Set the default executor used by :meth:`run_in_executor`. +Error Handling API +------------------ + +Allows to customize how exceptions are handled in the event loop. + +.. method:: BaseEventLoop.set_exception_handler(handler) + + Set *handler* as the new event loop exception handler. + + If *handler* is ``None``, the default exception handler will + be set. + + If *handler* is a callable object, it should have a + matching signature to ``(loop, context)``, where ``loop`` + will be a reference to the active event loop, ``context`` + will be a ``dict`` object (see :meth:`call_exception_handler` + documentation for details about context). + +.. method:: BaseEventLoop.default_exception_handler(context) + + Default exception handler. + + This is called when an exception occurs and no exception + handler is set, and can be called by a custom exception + handler that wants to defer to the default behavior. + + *context* parameter has the same meaning as in + :meth:`call_exception_handler`. + +.. method:: BaseEventLoop.call_exception_handler(context) + + Call the current event loop exception handler. + + *context* is a ``dict`` object containing the following keys + (new keys may be introduced later): + + * 'message': Error message; + * 'exception' (optional): Exception object; + * 'future' (optional): :class:`asyncio.Future` instance; + * 'handle' (optional): :class:`asyncio.Handle` instance; + * 'protocol' (optional): :ref:`Protocol ` instance; + * 'transport' (optional): :ref:`Transport ` instance; + * 'socket' (optional): :class:`socket.socket` instance. + + .. note:: + + Note: this method should not be overloaded in subclassed + event loops. For any custom exception handling, use + :meth:`set_exception_handler()` method. + Debug mode ---------- @@ -585,6 +636,20 @@ Coroutine to wait until service is closed. +Handle +------ + +.. class:: Handle + + A callback wrapper object returned by :func:`BaseEventLoop.call_soon`, + :func:`BaseEventLoop.call_soon_threadsafe`, :func:`BaseEventLoop.call_later`, + and :func:`BaseEventLoop.call_at`. + + .. method:: cancel() + + Cancel the call. + + .. _asyncio-hello-world-callback: Example: Hello World (callback) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 05:07:23 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 20 Feb 2014 05:07:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_update_logo_ur?= =?utf-8?q?l_=28=2320695=29?= Message-ID: <3fV2Lz5RD0z7Ljb@mail.python.org> http://hg.python.org/cpython/rev/0199bff14c5c changeset: 89292:0199bff14c5c branch: 2.7 parent: 89285:d11ca14c9a61 user: Benjamin Peterson date: Wed Feb 19 22:51:08 2014 -0500 summary: update logo url (#20695) files: Lib/test/test_urllibnet.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -184,7 +184,7 @@ "header is not an instance of mimetools.Message") def test_data_header(self): - logo = "http://www.python.org/community/logos/python-logo-master-v3-TM.png" + logo = "http://python.org/static/community_logos/python-logo-master-v3-TM.png" file_location, fileheaders = self.urlretrieve(logo) os.unlink(file_location) datevalue = fileheaders.getheader('Date') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 05:07:25 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 20 Feb 2014 05:07:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E1=29=3A_update_logo_ur?= =?utf-8?q?l_=28=2320695=29?= Message-ID: <3fV2M10h6pz7Ljl@mail.python.org> http://hg.python.org/cpython/rev/d4b9692ac75f changeset: 89293:d4b9692ac75f branch: 3.1 parent: 88454:715fd3d8ac93 user: Benjamin Peterson date: Wed Feb 19 22:55:16 2014 -0500 summary: update logo url (#20695) files: Lib/test/test_urllibnet.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -172,7 +172,7 @@ "header is not an instance of email.message.Message") def test_data_header(self): - logo = "http://www.python.org/community/logos/python-logo-master-v3-TM.png" + logo = "http://python.org/static/community_logos/python-logo-master-v3-TM.png" file_location, fileheaders = self.urlretrieve(logo) os.unlink(file_location) datevalue = fileheaders.get('Date') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 05:07:26 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 20 Feb 2014 05:07:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E1=29=3A_open_retrieved?= =?utf-8?q?_file_in_binary_mode=2C_since_it=27s_now_compressed?= Message-ID: <3fV2M222Knz7Ljp@mail.python.org> http://hg.python.org/cpython/rev/fbb4d48046e5 changeset: 89294:fbb4d48046e5 branch: 3.1 user: Benjamin Peterson date: Wed Feb 19 22:56:35 2014 -0500 summary: open retrieved file in binary mode, since it's now compressed files: Lib/test/test_urllibnet.py | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -109,7 +109,7 @@ # Make sure fd returned by fileno is valid. open_url = self.urlopen("http://www.python.org/", timeout=None) fd = open_url.fileno() - FILE = os.fdopen(fd, encoding='utf-8') + FILE = os.fdopen(fd, 'rb') try: self.assertTrue(FILE.read(), "reading from file created using fd " "returned by fileno failed") @@ -143,7 +143,7 @@ file_location,info = self.urlretrieve("http://www.python.org/") self.assertTrue(os.path.exists(file_location), "file location returned by" " urlretrieve is not a valid path") - FILE = open(file_location, encoding='utf-8') + FILE = open(file_location, 'rb') try: self.assertTrue(FILE.read(), "reading from the file location returned" " by urlretrieve failed") @@ -157,7 +157,7 @@ support.TESTFN) self.assertEqual(file_location, support.TESTFN) self.assertTrue(os.path.exists(file_location)) - FILE = open(file_location, encoding='utf-8') + FILE = open(file_location, 'rb') try: self.assertTrue(FILE.read(), "reading from temporary file failed") finally: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 05:07:27 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 20 Feb 2014 05:07:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_open_retrieved?= =?utf-8?q?_file_in_binary_mode=2C_since_it=27s_now_compressed?= Message-ID: <3fV2M33QlPz7Ljh@mail.python.org> http://hg.python.org/cpython/rev/af54817840a8 changeset: 89295:af54817840a8 branch: 3.2 parent: 88455:9c56217e5c79 user: Benjamin Peterson date: Wed Feb 19 22:56:35 2014 -0500 summary: open retrieved file in binary mode, since it's now compressed files: Lib/test/test_urllibnet.py | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -106,7 +106,7 @@ # Make sure fd returned by fileno is valid. with self.urlopen("http://www.python.org/", timeout=None) as open_url: fd = open_url.fileno() - with os.fdopen(fd, encoding='utf-8') as f: + with os.fdopen(fd, 'rb') as f: self.assertTrue(f.read(), "reading from file created using fd " "returned by fileno failed") @@ -151,7 +151,7 @@ with self.urlretrieve("http://www.python.org/") as (file_location, info): self.assertTrue(os.path.exists(file_location), "file location returned by" " urlretrieve is not a valid path") - with open(file_location, encoding='utf-8') as f: + with open(file_location, 'rb') as f: self.assertTrue(f.read(), "reading from the file location returned" " by urlretrieve failed") @@ -161,7 +161,7 @@ support.TESTFN) as (file_location, info): self.assertEqual(file_location, support.TESTFN) self.assertTrue(os.path.exists(file_location)) - with open(file_location, encoding='utf-8') as f: + with open(file_location, 'rb') as f: self.assertTrue(f.read(), "reading from temporary file failed") def test_header(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 05:07:28 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 20 Feb 2014 05:07:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_update_logo_ur?= =?utf-8?q?l_=28=2320695=29?= Message-ID: <3fV2M44kQ1z7Ljc@mail.python.org> http://hg.python.org/cpython/rev/29b1eebecb8e changeset: 89296:29b1eebecb8e branch: 3.2 user: Benjamin Peterson date: Wed Feb 19 22:55:16 2014 -0500 summary: update logo url (#20695) files: Lib/test/test_urllibnet.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -171,7 +171,7 @@ "info is not an instance of email.message.Message") def test_data_header(self): - logo = "http://www.python.org/community/logos/python-logo-master-v3-TM.png" + logo = "http://www.python.org/static/community_logos/python-logo-master-v3-TM.png" with self.urlretrieve(logo) as (file_location, fileheaders): datevalue = fileheaders.get('Date') dateformat = '%a, %d %b %Y %H:%M:%S GMT' -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 05:07:29 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 20 Feb 2014 05:07:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_bump_Python-as?= =?utf-8?b?dC5j?= Message-ID: <3fV2M56G6Pz7Ljg@mail.python.org> http://hg.python.org/cpython/rev/8d1528dddc7d changeset: 89297:8d1528dddc7d branch: 3.3 parent: 89279:d89178781873 user: Benjamin Peterson date: Wed Feb 19 23:05:26 2014 -0500 summary: bump Python-ast.c files: Python/Python-ast.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/Python-ast.c b/Python/Python-ast.c --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -6960,11 +6960,11 @@ PyObject *req_type[3]; char *req_name[] = {"Module", "Expression", "Interactive"}; int isinstance; - + req_type[0] = (PyObject*)Module_type; req_type[1] = (PyObject*)Expression_type; req_type[2] = (PyObject*)Interactive_type; - + assert(0 <= mode && mode <= 2); init_types(); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 05:07:31 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 20 Feb 2014 05:07:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_merge_3=2E2_=28=2320695=29?= Message-ID: <3fV2M70nbyz7Ljh@mail.python.org> http://hg.python.org/cpython/rev/c9261cf05db6 changeset: 89298:c9261cf05db6 branch: 3.3 parent: 89297:8d1528dddc7d parent: 89296:29b1eebecb8e user: Benjamin Peterson date: Wed Feb 19 23:06:24 2014 -0500 summary: merge 3.2 (#20695) files: Lib/test/test_urllibnet.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -103,7 +103,7 @@ # Make sure fd returned by fileno is valid. with self.urlopen("http://www.python.org/", timeout=None) as open_url: fd = open_url.fileno() - with os.fdopen(fd, encoding='utf-8') as f: + with os.fdopen(fd, 'rb') as f: self.assertTrue(f.read(), "reading from file created using fd " "returned by fileno failed") @@ -151,7 +151,7 @@ with self.urlretrieve("http://www.python.org/") as (file_location, info): self.assertTrue(os.path.exists(file_location), "file location returned by" " urlretrieve is not a valid path") - with open(file_location, encoding='utf-8') as f: + with open(file_location, 'rb') as f: self.assertTrue(f.read(), "reading from the file location returned" " by urlretrieve failed") @@ -161,7 +161,7 @@ support.TESTFN) as (file_location, info): self.assertEqual(file_location, support.TESTFN) self.assertTrue(os.path.exists(file_location)) - with open(file_location, encoding='utf-8') as f: + with open(file_location, 'rb') as f: self.assertTrue(f.read(), "reading from temporary file failed") def test_header(self): @@ -170,7 +170,7 @@ self.assertIsInstance(info, email.message.Message, "info is not an instance of email.message.Message") - logo = "http://www.python.org/community/logos/python-logo-master-v3-TM.png" + logo = "http://www.python.org/static/community_logos/python-logo-master-v3-TM.png" def test_data_header(self): with self.urlretrieve(self.logo) as (file_location, fileheaders): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 05:07:32 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 20 Feb 2014 05:07:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4zICgjMjA2OTUp?= Message-ID: <3fV2M82kpJz7LkB@mail.python.org> http://hg.python.org/cpython/rev/0399e842073a changeset: 89299:0399e842073a parent: 89291:58fd64e55b29 parent: 89298:c9261cf05db6 user: Benjamin Peterson date: Wed Feb 19 23:06:41 2014 -0500 summary: merge 3.3 (#20695) files: Lib/test/test_urllibnet.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -103,7 +103,7 @@ # Make sure fd returned by fileno is valid. with self.urlopen("http://www.python.org/", timeout=None) as open_url: fd = open_url.fileno() - with os.fdopen(fd, encoding='utf-8') as f: + with os.fdopen(fd, 'rb') as f: self.assertTrue(f.read(), "reading from file created using fd " "returned by fileno failed") @@ -150,7 +150,7 @@ with self.urlretrieve("http://www.python.org/") as (file_location, info): self.assertTrue(os.path.exists(file_location), "file location returned by" " urlretrieve is not a valid path") - with open(file_location, encoding='utf-8') as f: + with open(file_location, 'rb') as f: self.assertTrue(f.read(), "reading from the file location returned" " by urlretrieve failed") @@ -160,7 +160,7 @@ support.TESTFN) as (file_location, info): self.assertEqual(file_location, support.TESTFN) self.assertTrue(os.path.exists(file_location)) - with open(file_location, encoding='utf-8') as f: + with open(file_location, 'rb') as f: self.assertTrue(f.read(), "reading from temporary file failed") def test_header(self): @@ -169,7 +169,7 @@ self.assertIsInstance(info, email.message.Message, "info is not an instance of email.message.Message") - logo = "http://www.python.org/community/logos/python-logo-master-v3-TM.png" + logo = "http://www.python.org/static/community_logos/python-logo-master-v3-TM.png" def test_data_header(self): with self.urlretrieve(self.logo) as (file_location, fileheaders): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 08:16:56 2014 From: python-checkins at python.org (yury.selivanov) Date: Thu, 20 Feb 2014 08:16:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_experts=3A_Add_yselivanov?= =?utf-8?q?_for_asyncio?= Message-ID: <3fV6Yh1B4Lz7LjT@mail.python.org> http://hg.python.org/devguide/rev/22a5743e1cbf changeset: 669:22a5743e1cbf user: Yury Selivanov date: Thu Feb 20 02:16:42 2014 -0500 summary: experts: Add yselivanov for asyncio files: experts.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/experts.rst b/experts.rst --- a/experts.rst +++ b/experts.rst @@ -56,7 +56,7 @@ array ast benjamin.peterson asynchat josiahcarlson, giampaolo.rodola, stutzbach -asyncio gvanrossum, haypo, pitrou +asyncio gvanrossum, haypo, pitrou, yselivanov asyncore josiahcarlson, giampaolo.rodola, stutzbach atexit audioop -- Repository URL: http://hg.python.org/devguide From solipsis at pitrou.net Thu Feb 20 09:36:49 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 20 Feb 2014 09:36:49 +0100 Subject: [Python-checkins] Daily reference leaks (58fd64e55b29): sum=0 Message-ID: results for 58fd64e55b29 on branch "default" -------------------------------------------- test_site leaked [2, 0, -2] references, sum=0 test_site leaked [2, 0, -2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogd9Pxd9', '-x'] From python-checkins at python.org Thu Feb 20 10:13:07 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 20 Feb 2014 10:13:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Esubprocess=3A_Fi?= =?utf-8?q?x_a_race_condition_in_communicate=28=29?= Message-ID: <3fV97l4NYhz7Lk6@mail.python.org> http://hg.python.org/cpython/rev/c3abdf016b18 changeset: 89300:c3abdf016b18 user: Victor Stinner date: Thu Feb 20 10:12:59 2014 +0100 summary: asyncio.subprocess: Fix a race condition in communicate() Use self._loop instead of self._transport._loop, because transport._loop is set to None at process exit. files: Lib/asyncio/subprocess.py | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/subprocess.py b/Lib/asyncio/subprocess.py --- a/Lib/asyncio/subprocess.py +++ b/Lib/asyncio/subprocess.py @@ -146,7 +146,6 @@ @tasks.coroutine def communicate(self, input=None): - loop = self._transport._loop if input: stdin = self._feed_stdin(input) else: @@ -160,7 +159,7 @@ else: stderr = self._noop() stdin, stdout, stderr = yield from tasks.gather(stdin, stdout, stderr, - loop=loop) + loop=self._loop) yield from self.wait() return (stdout, stderr) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 10:34:13 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 20 Feb 2014 10:34:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Fix_=5FProactor?= =?utf-8?q?WritePipeTransport=2E=5Fpipe=5Fclosed=28=29?= Message-ID: <3fV9c55gPDzSTC@mail.python.org> http://hg.python.org/cpython/rev/c412243b9d61 changeset: 89301:c412243b9d61 user: Victor Stinner date: Thu Feb 20 10:33:01 2014 +0100 summary: asyncio: Fix _ProactorWritePipeTransport._pipe_closed() The "exc" variable was not defined, pass a BrokenPipeError exception instead. files: Lib/asyncio/proactor_events.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -275,7 +275,7 @@ assert fut is self._read_fut, (fut, self._read_fut) self._read_fut = None if self._write_fut is not None: - self._force_close(exc) + self._force_close(BrokenPipeError()) else: self.close() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 10:38:10 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 20 Feb 2014 10:38:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_remove_unused_i?= =?utf-8?q?mports_and_unused_variables_noticed_by_pyflakes?= Message-ID: <3fV9hf0GZLz7LjN@mail.python.org> http://hg.python.org/cpython/rev/3e19634b396f changeset: 89302:3e19634b396f user: Victor Stinner date: Thu Feb 20 10:37:27 2014 +0100 summary: asyncio: remove unused imports and unused variables noticed by pyflakes files: Lib/asyncio/events.py | 3 --- Lib/asyncio/futures.py | 1 - Lib/asyncio/tasks.py | 2 -- Lib/asyncio/test_utils.py | 2 +- Lib/asyncio/unix_events.py | 1 - Lib/asyncio/windows_events.py | 1 - Lib/selectors.py | 3 +-- 7 files changed, 2 insertions(+), 11 deletions(-) diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -9,12 +9,9 @@ ] import subprocess -import sys import threading import socket -from .log import logger - class Handle: """Object returned by callback registration methods.""" diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -11,7 +11,6 @@ import traceback from . import events -from .log import logger # States for Future. _PENDING = 'PENDING' diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -7,7 +7,6 @@ 'gather', 'shield', ] -import collections import concurrent.futures import functools import inspect @@ -486,7 +485,6 @@ if isinstance(fs, futures.Future) or iscoroutine(fs): raise TypeError("expect a list of futures, not %s" % type(fs).__name__) loop = loop if loop is not None else events.get_event_loop() - deadline = None if timeout is None else loop.time() + timeout todo = {async(f, loop=loop) for f in set(fs)} from .queues import Queue # Import here to avoid circular import problem. done = Queue(loop=loop) diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -15,7 +15,7 @@ import unittest.mock from http.server import HTTPServer -from wsgiref.simple_server import make_server, WSGIRequestHandler, WSGIServer +from wsgiref.simple_server import WSGIRequestHandler, WSGIServer try: import ssl diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -15,7 +15,6 @@ from . import base_subprocess from . import constants from . import events -from . import protocols from . import selector_events from . import tasks from . import transports diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -5,7 +5,6 @@ import math import socket import struct -import subprocess import weakref from . import events diff --git a/Lib/selectors.py b/Lib/selectors.py --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -5,9 +5,8 @@ """ -from abc import ABCMeta, abstractmethod, abstractproperty +from abc import ABCMeta, abstractmethod from collections import namedtuple, Mapping -import functools import math import select import sys -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 16:53:19 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 20 Feb 2014 16:53:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Fix_=5Fcheck=5F?= =?utf-8?q?resolved=5Faddress=28=29_for_IPv6_address?= Message-ID: <3fVL1W5kQpz7LkB@mail.python.org> http://hg.python.org/cpython/rev/d1f0ec5a9317 changeset: 89303:d1f0ec5a9317 user: Victor Stinner date: Thu Feb 20 16:43:09 2014 +0100 summary: asyncio: Fix _check_resolved_address() for IPv6 address files: Lib/asyncio/base_events.py | 7 +++++-- 1 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -45,10 +45,13 @@ # Ensure that the address is already resolved to avoid the trap of hanging # the entire event loop when the address requires doing a DNS lookup. family = sock.family - if family not in (socket.AF_INET, socket.AF_INET6): + if family == socket.AF_INET: + host, port = address + elif family == socket.AF_INET6: + host, port, flow_info, scope_id = address + else: return - host, port = address type_mask = 0 if hasattr(socket, 'SOCK_NONBLOCK'): type_mask |= socket.SOCK_NONBLOCK -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 17:01:21 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 20 Feb 2014 17:01:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_ops=2C_and_now_?= =?utf-8?q?fix_also_the_unit_test_for_IPv6_address=3A?= Message-ID: <3fVLBn4D8tz7Mjp@mail.python.org> http://hg.python.org/cpython/rev/03b14690a9be changeset: 89304:03b14690a9be user: Victor Stinner date: Thu Feb 20 17:01:11 2014 +0100 summary: asyncio: ops, and now fix also the unit test for IPv6 address: test_sock_connect_address() files: Lib/test/test_asyncio/test_events.py | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1335,12 +1335,11 @@ 'selector': self.loop._selector.__class__.__name__}) def test_sock_connect_address(self): - families = [socket.AF_INET] + families = [(socket.AF_INET, ('www.python.org', 80))] if support.IPV6_ENABLED: - families.append(socket.AF_INET6) + families.append((socket.AF_INET6, ('www.python.org', 80, 0, 0))) - address = ('www.python.org', 80) - for family in families: + for family, address in families: for sock_type in (socket.SOCK_STREAM, socket.SOCK_DGRAM): sock = socket.socket(family, sock_type) with sock: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 19:59:21 2014 From: python-checkins at python.org (yury.selivanov) Date: Thu, 20 Feb 2014 19:59:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Misc/NEWS=3A_Add_some_miss?= =?utf-8?q?ing_news_items_re_asyncio=2E?= Message-ID: <3fVQ894zgfzQMd@mail.python.org> http://hg.python.org/cpython/rev/db749f0c6567 changeset: 89305:db749f0c6567 user: Yury Selivanov date: Thu Feb 20 13:59:14 2014 -0500 summary: Misc/NEWS: Add some missing news items re asyncio. files: Misc/NEWS | 19 +++++++++++++++++++ 1 files changed, 19 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -72,6 +72,25 @@ chains. Make its behaviour consistent with bound methods first argument. Patch by Nick Coghlan and Yury Selivanov. +- Issue #20566: Change asyncio.as_completed() to use a Queue, to + avoid O(N**2) behavior. + +- Issue #20704: Implement new debug API in asyncio. Add new methods + BaseEventLoop.set_debug() and BaseEventLoop.get_debug(). + Add support for setting 'asyncio.tasks._DEBUG' variable with + 'PYTHONASYNCIODEBUG' environment variable. + +- asyncio: Refactoring and fixes: BaseEventLoop.sock_connect() raises an + error if the address is not resolved; use __slots__ in Handle and + TimerHandle; as_completed() and wait() raise TypeError if the passed + list of Futures is a single Future; call_soon() and other 'call_*()' + functions raise TypeError if the passed callback is a coroutine + function; _ProactorBasePipeTransport uses _FlowControlMixin; + WriteTransport.set_write_buffer_size() calls _maybe_pause_protocol() + to consider pausing receiving if the watermark limits have changed; + fix _check_resolved_address() for IPv6 address; and other minor + improvements, along with multiple documentation updates. + Tests ----- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 20:10:21 2014 From: python-checkins at python.org (yury.selivanov) Date: Thu, 20 Feb 2014 20:10:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Edocs=3A_Improve_?= =?utf-8?q?documentation_of_Streams=2E_Issue_=2320696=2E?= Message-ID: <3fVQNs4kSHz7Lk3@mail.python.org> http://hg.python.org/cpython/rev/1c35d3114ea1 changeset: 89306:1c35d3114ea1 user: Yury Selivanov date: Thu Feb 20 14:10:02 2014 -0500 summary: asyncio.docs: Improve documentation of Streams. Issue #20696. files: Doc/library/asyncio-stream.rst | 72 +++++++++++++-------- 1 files changed, 43 insertions(+), 29 deletions(-) diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -34,7 +34,7 @@ .. function:: start_server(client_connected_cb, host=None, port=None, \*, loop=None, limit=None, **kwds) - Start a socket server, call back for each client connected. + Start a socket server, with a callback for each client connected. The first parameter, *client_connected_cb*, takes two parameters: *client_reader*, *client_writer*. *client_reader* is a @@ -58,6 +58,29 @@ This function returns a :ref:`coroutine object `. +.. function:: open_unix_connection(path=None, \*, loop=None, limit=None, **kwds) + + A wrapper for :meth:`~BaseEventLoop.create_unix_connection()` returning + a (reader, writer) pair. + + See :func:`open_connection` for information about return value and other + details. + + This function returns a :ref:`coroutine object `. + + Availability: UNIX. + +.. function:: start_unix_server(client_connected_cb, path=None, \*, loop=None, limit=None, **kwds) + + Start a UNIX Domain Socket server, with a callback for each client connected. + + See :func:`start_server` for information about return value and other + details. + + This function returns a :ref:`coroutine object `. + + Availability: UNIX. + StreamReader ============ @@ -70,11 +93,12 @@ .. method:: feed_eof() - XXX + Acknowledge the EOF. .. method:: feed_data(data) - XXX + Feed *data* bytes in the internal buffer. Any operations waiting + for the data will be resumed. .. method:: set_exception(exc) @@ -86,13 +110,23 @@ .. method:: read(n=-1) - XXX + Read up to *n* bytes. If *n* is not provided, or set to ``-1``, + read until EOF and return all read bytes. + + If the EOF was received and the internal buffer is empty, + return an empty ``bytes`` object. This method returns a :ref:`coroutine object `. .. method:: readline() - XXX + Read one line, where "line" is a sequence of bytes ending with ``\n``. + + If EOF is received, and ``\n`` was not found, the method will + return the partial read bytes. + + If the EOF was received and the internal buffer is empty, + return an empty ``bytes`` object. This method returns a :ref:`coroutine object `. @@ -105,6 +139,10 @@ This method returns a :ref:`coroutine object `. + .. method:: at_eof() + + Return ``True`` if the buffer is empty and :meth:`feed_eof` was called. + StreamWriter ============ @@ -186,30 +224,6 @@ potential uses, and to prevent the user of the :class:`StreamReader` to accidentally call inappropriate methods of the protocol.) - .. method:: connection_made(transport) - - XXX - - .. method:: connection_lost(exc) - - XXX - - .. method:: data_received(data) - - XXX - - .. method:: eof_received() - - XXX - - .. method:: pause_writing() - - XXX - - .. method:: resume_writing() - - XXX - IncompleteReadError =================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 22:00:19 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 20 Feb 2014 22:00:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_=5Fcheck=5Freso?= =?utf-8?q?lved=5Faddress=28=29_must_also_accept_IPv6_without_flow=5Finfo_?= =?utf-8?q?and?= Message-ID: <3fVSql2jMWz7MTD@mail.python.org> http://hg.python.org/cpython/rev/96e078663083 changeset: 89307:96e078663083 user: Victor Stinner date: Thu Feb 20 21:59:38 2014 +0100 summary: asyncio: _check_resolved_address() must also accept IPv6 without flow_info and scope_id: (host, port). files: Lib/asyncio/base_events.py | 2 +- Lib/test/test_asyncio/test_events.py | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -48,7 +48,7 @@ if family == socket.AF_INET: host, port = address elif family == socket.AF_INET6: - host, port, flow_info, scope_id = address + host, port = address[:2] else: return diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1335,11 +1335,14 @@ 'selector': self.loop._selector.__class__.__name__}) def test_sock_connect_address(self): - families = [(socket.AF_INET, ('www.python.org', 80))] + addresses = [(socket.AF_INET, ('www.python.org', 80))] if support.IPV6_ENABLED: - families.append((socket.AF_INET6, ('www.python.org', 80, 0, 0))) + addresses.extend(( + (socket.AF_INET6, ('www.python.org', 80)), + (socket.AF_INET6, ('www.python.org', 80, 0, 0)), + )) - for family, address in families: + for family, address in addresses: for sock_type in (socket.SOCK_STREAM, socket.SOCK_DGRAM): sock = socket.socket(family, sock_type) with sock: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 22:14:25 2014 From: python-checkins at python.org (larry.hastings) Date: Thu, 20 Feb 2014 22:14:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?release=3A_Updates_for_threefourtool?= =?utf-8?q?=2Epy=2E?= Message-ID: <3fVT810VD4z7Mk4@mail.python.org> http://hg.python.org/release/rev/474632cb9ced changeset: 73:474632cb9ced user: Larry Hastings date: Thu Feb 20 13:14:22 2014 -0800 summary: Updates for threefourtool.py. files: 3.4/threefourtool.py | 53 ++++++++++++++++++++++++++++--- 1 files changed, 47 insertions(+), 6 deletions(-) diff --git a/3.4/threefourtool.py b/3.4/threefourtool.py --- a/3.4/threefourtool.py +++ b/3.4/threefourtool.py @@ -1,5 +1,13 @@ #!/usr/bin/env python3 +# +# todo: +# +# change status page +# * get rid of "merged" vs "unmerged" lists +# instead, just have one list, with each revision marked merged or unmerged. +# make it obvious, like have unmerged indented or something. + import atexit import collections import datetime @@ -29,6 +37,8 @@ s = str(datetime.datetime.now()) for c in "- :": s = s.replace(c, '.') + fields = s.split('.') + s = '.'.join(fields[:-1]) return s def line_to_rev(line): @@ -428,10 +438,12 @@ text, cmd = commands[i] commands_run.add(text) if isinstance(cmd, str): + print() cmd = cmd.format_map(u) result = os.system(cmd) print() - print("Result:", result) + if result != 0: + print("Process return code:", result) else: cmd() @@ -593,19 +605,30 @@ r = r.split()[0].strip() u['threefour picked revision'] = r + show_patch = False + def toggle_patch(): + nonlocal show_patch + show_patch = not show_patch + def mark_as_picked(): del self.unfinished['default picked revision'] + print() + print("_" * 79) + print("_" * 79) + print() while u.get('default picked revision'): commands = [] commands.append(("Update to appropriate revision in 3.4 branch", "hg update -r {threefour graft here}")) commands.append(("Graft revision", "hg graft {default picked revision}")) + commands.append(("Patch revision (only if graft fails)", toggle_patch)) - commands.append(("[graft failed step 1] Generate patch", "/usr/bin/hg diff -r {default diff from} -r {default picked revision} > {patch path}")) - commands.append(("[graft failed step 2] Inspect patch", "{EDITOR} {patch path}")) - commands.append(("[graft failed step 3] Apply patch", "/usr/bin/patch -p1 < {patch path}")) - commands.append(("[graft failed step 4] Check in patch", "/usr/bin/hg ci --user '{user}' --date '{date}' --logfile '{commit message path}'")) + if show_patch: + commands.append(("[graft failed step 1] Generate patch", "/usr/bin/hg diff -r {default diff from} -r {default picked revision} > {patch path}")) + commands.append(("[graft failed step 2] Inspect patch", "{EDITOR} {patch path}")) + commands.append(("[graft failed step 3] Apply patch", "/usr/bin/patch -p1 < {patch path}")) + commands.append(("[graft failed step 4] Check in patch", "/usr/bin/hg ci --user '{user}' --date '{date}' --logfile '{commit message path}'")) if u.get('threefour rebase from'): commands.append(("Detect new revision", detect_new_revision)) @@ -615,8 +638,12 @@ commands.append(("Mark revision as picked", mark_as_picked)) + commands.append(("Print details of picked revision", "hg log -r {default picked revision}")) + print() - print("Picking revision {default picked revision}:".format_map(u)) + total = len(u['original picked revisions']) + current = len(u['picked revisions']) + print("Picking revision {default picked revision}".format_map(u) + " ({}/{}):".format(total-current, total)) self._run_command(commands, u) def finish(self): @@ -688,6 +715,20 @@ os.system("rsync -av * midwinter.com:public_html/3.4.status") + def asyncio(self): + for dir in ("Lib/asyncio", "Lib/test/test_asyncio"): + os.chdir("/home/larry/src/python/3.4/" + dir) + os.system("diff . /home/larry/src/python/trunk/" + dir) + os.chdir("/home/larry/src/python/3.4/Doc/library") + for file in glob.glob("asyncio*"): + f1 = open(file, "rt").read() + f2 = open("/home/larry/src/python/trunk/Doc/library/" + file, "rt").read() + if f1 != f2: + cmd = "diff {file} /home/larry/src/python/trunk/Doc/library/{file}".format(file=file) + print(cmd) + os.system(cmd) + + t = Tool() -- Repository URL: http://hg.python.org/release From python-checkins at python.org Thu Feb 20 22:21:01 2014 From: python-checkins at python.org (yury.selivanov) Date: Thu, 20 Feb 2014 22:21:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Edocs=3A_Improve_?= =?utf-8?q?wordings=3B_add_a_note_to_the_Coroutines_section=2E_Issue?= Message-ID: <3fVTHd2DXzz7MjB@mail.python.org> http://hg.python.org/cpython/rev/cd23d0c3f850 changeset: 89308:cd23d0c3f850 user: Yury Selivanov date: Thu Feb 20 16:20:44 2014 -0500 summary: asyncio.docs: Improve wordings; add a note to the Coroutines section. Issue #20706 files: Doc/library/asyncio-eventloop.rst | 45 +++++++++--------- Doc/library/asyncio-stream.rst | 14 ++-- Doc/library/asyncio-sync.rst | 14 ++-- Doc/library/asyncio-task.rst | 14 +++++- 4 files changed, 49 insertions(+), 38 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -102,7 +102,8 @@ Run until the :class:`Future` is done. - If the argument is a coroutine, it is wrapped in a :class:`Task`. + If the argument is a :ref:`coroutine `, it is wrapped + in a :class:`Task`. Return the Future's result, or raise its exception. @@ -207,7 +208,7 @@ socket type :py:data:`~socket.SOCK_STREAM`. *protocol_factory* must be a callable returning a :ref:`protocol ` instance. - This method returns a :ref:`coroutine object ` which will try to + 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. @@ -274,7 +275,7 @@ :py:data:`~socket.AF_INET6` depending on *host* (or *family* if specified), socket type :py:data:`~socket.SOCK_DGRAM`. - This method returns a :ref:`coroutine object ` which will try to + 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. @@ -288,7 +289,7 @@ family is used to communicate between processes on the same machine efficiently. - This method returns a :ref:`coroutine object ` which will try to + 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. @@ -302,8 +303,8 @@ .. method:: BaseEventLoop.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) - A :ref:`coroutine function ` which creates a TCP server bound to host and - port. + A :ref:`coroutine ` method which creates a TCP server bound to + host and port. The return value is a :class:`AbstractServer` object which can be used to stop the service. @@ -332,8 +333,6 @@ expire. If not specified will automatically be set to True on UNIX. - This method returns a :ref:`coroutine object `. - .. seealso:: The function :func:`start_server` creates a (:class:`StreamReader`, @@ -380,7 +379,7 @@ representing the data received. The maximum amount of data to be received at once is specified by *nbytes*. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. seealso:: @@ -392,9 +391,9 @@ This method continues to send data from *data* until either all data has been sent or an 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 sent. + any, was successfully processed by the receiving end of the connection. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. seealso:: @@ -410,7 +409,7 @@ :py:data:`~socket.AF_INET` and :py:data:`~socket.AF_INET6` address families. Use :meth:`getaddrinfo` to resolve the hostname asynchronously. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. seealso:: @@ -427,7 +426,7 @@ and *address* is the address bound to the socket on the other end of the connection. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. seealso:: @@ -440,13 +439,13 @@ .. method:: BaseEventLoop.getaddrinfo(host, port, \*, family=0, type=0, proto=0, flags=0) - Similar to the :meth:`socket.getaddrinfo` function, but return a - :ref:`coroutine object `. + This method is a :ref:`coroutine `, similar to + :meth:`socket.getaddrinfo` function but non-blocking. .. method:: BaseEventLoop.getnameinfo(sockaddr, flags=0) - Similar to the :meth:`socket.getnameinfo` function, but return a - :ref:`coroutine object `. + This method is a :ref:`coroutine `, similar to + :meth:`socket.getnameinfo` function but non-blocking. Running subprocesses @@ -472,7 +471,7 @@ XXX - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. See the constructor of the :class:`subprocess.Popen` class for parameters. @@ -480,7 +479,7 @@ XXX - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. See the constructor of the :class:`subprocess.Popen` class for parameters. @@ -493,7 +492,7 @@ Return pair (transport, protocol), where transport support :class:`ReadTransport` interface. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. method:: BaseEventLoop.connect_write_pipe(protocol_factory, pipe) @@ -504,7 +503,7 @@ Return pair (transport, protocol), where transport support :class:`WriteTransport` interface. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. seealso:: @@ -549,6 +548,8 @@ *executor* is a :class:`~concurrent.futures.Executor` instance, the default executor is used if *executor* is ``None``. + This method is a :ref:`coroutine `. + .. method:: BaseEventLoop.set_default_executor(executor) Set the default executor used by :meth:`run_in_executor`. @@ -633,7 +634,7 @@ .. method:: wait_closed() - Coroutine to wait until service is closed. + A :ref:`coroutine ` to wait until service is closed. Handle diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -30,7 +30,7 @@ :class:`StreamReaderProtocol` classes, just copy the code -- there's really nothing special here except some convenience.) - This function returns a :ref:`coroutine object `. + This function is a :ref:`coroutine `. .. function:: start_server(client_connected_cb, host=None, port=None, \*, loop=None, limit=None, **kwds) @@ -56,7 +56,7 @@ The return value is the same as :meth:`~BaseEventLoop.create_server()`, i.e. a :class:`AbstractServer` object which can be used to stop the service. - This function returns a :ref:`coroutine object `. + This function is a :ref:`coroutine `. .. function:: open_unix_connection(path=None, \*, loop=None, limit=None, **kwds) @@ -66,7 +66,7 @@ See :func:`open_connection` for information about return value and other details. - This function returns a :ref:`coroutine object `. + This function is a :ref:`coroutine `. Availability: UNIX. @@ -77,7 +77,7 @@ See :func:`start_server` for information about return value and other details. - This function returns a :ref:`coroutine object `. + This function is a :ref:`coroutine `. Availability: UNIX. @@ -116,7 +116,7 @@ If the EOF was received and the internal buffer is empty, return an empty ``bytes`` object. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. method:: readline() @@ -128,7 +128,7 @@ If the EOF was received and the internal buffer is empty, return an empty ``bytes`` object. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. method:: readexactly(n) @@ -137,7 +137,7 @@ :attr:`IncompleteReadError.partial` attribute of the exception contains the partial read bytes. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. method:: at_eof() diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst --- a/Doc/library/asyncio-sync.rst +++ b/Doc/library/asyncio-sync.rst @@ -124,7 +124,7 @@ Otherwise, block until another coroutine calls :meth:`set` to set the flag to true, then return ``True``. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. Condition @@ -175,7 +175,7 @@ condition variable in another coroutine. Once awakened, it re-acquires the lock and returns ``True``. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. method:: wait_for(predicate) @@ -184,7 +184,7 @@ The predicate should be a callable which result will be interpreted as a boolean value. The final predicate value is the return value. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. Semaphores @@ -217,7 +217,7 @@ until some other coroutine has called :meth:`release` to make it larger than ``0``, and then return ``True``. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. method:: locked() @@ -279,7 +279,7 @@ If you yield from :meth:`get()`, wait until a item is available. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. method:: get_nowait() @@ -295,7 +295,7 @@ If you yield from ``put()``, wait until a free slot is available before adding item. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. method:: put_nowait(item) @@ -350,7 +350,7 @@ it is complete. When the count of unfinished tasks drops to zero, :meth:`join` unblocks. - This method returns a :ref:`coroutine object `. + This method is a :ref:`coroutine `. .. method:: task_done() diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -64,6 +64,14 @@ message is logged. See :ref:`Detect coroutines never scheduled `. +.. note:: + + In this documentation, some methods are documented as coroutines, + even if they are plain Python functions returning a :class:`Future`. + This is intentional to have a freedom of tweaking the implementation + of these functions in the future. If such a function is needed to be + used in a callback-style code, wrap its result with :func:`async`. + .. _asyncio-hello-world-coroutine: @@ -440,7 +448,7 @@ .. function:: sleep(delay, result=None, \*, loop=None) - Create a :ref:`coroutine object ` that completes after a given + Create a :ref:`coroutine ` that completes after a given time (in seconds). If *result* is provided, it is produced to the caller when the coroutine completes. @@ -505,7 +513,7 @@ | | futures finish or are cancelled. | +-----------------------------+----------------------------------------+ - This function returns a :ref:`coroutine object `. + This function is a :ref:`coroutine `. Usage:: @@ -529,6 +537,8 @@ cancels the task and raises :exc:`TimeoutError`. To avoid the task cancellation, wrap it in :func:`shield`. + This function is a :ref:`coroutine `. + Usage:: result = yield from asyncio.wait_for(fut, 60.0) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 22:40:20 2014 From: python-checkins at python.org (zach.ware) Date: Thu, 20 Feb 2014 22:40:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwMjIx?= =?utf-8?q?=3A_Removed_conflicting_=28or_circular=29_hypot_definition?= Message-ID: <3fVTjw6qkcz7Llb@mail.python.org> http://hg.python.org/cpython/rev/9aedb876c2d7 changeset: 89309:9aedb876c2d7 branch: 3.3 parent: 89298:c9261cf05db6 user: Zachary Ware date: Thu Feb 20 15:36:34 2014 -0600 summary: Issue #20221: Removed conflicting (or circular) hypot definition when compiled with VS 2010 or above. Initial patch by Tabrez Mohammed. files: Misc/NEWS | 3 +++ PC/pyconfig.h | 4 ++++ 2 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -141,6 +141,9 @@ Build ----- +- Issue #20221: Removed conflicting (or circular) hypot definition when + compiled with VS 2010 or above. Initial patch by Tabrez Mohammed. + - Issue #20609: Restored the ability to build 64-bit Windows binaries on 32-bit Windows, which was broken by the change in issue #19788. diff --git a/PC/pyconfig.h b/PC/pyconfig.h --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -213,7 +213,11 @@ #define Py_IS_INFINITY(X) (!_finite(X) && !_isnan(X)) #define Py_IS_FINITE(X) _finite(X) #define copysign _copysign + +/* VS 2010 and above already defines hypot as _hypot */ +#if _MSC_VER < 1600 #define hypot _hypot +#endif /* Side by Side assemblies supported in VS 2005 and VS 2008 but not 2010*/ #if _MSC_VER >= 1400 && _MSC_VER < 1600 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 22:40:22 2014 From: python-checkins at python.org (zach.ware) Date: Thu, 20 Feb 2014 22:40:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320221=3A_Removed_conflicting_=28or_circular=29_?= =?utf-8?q?hypot_definition?= Message-ID: <3fVTjy258vz7MjK@mail.python.org> http://hg.python.org/cpython/rev/bf413a97f1a9 changeset: 89310:bf413a97f1a9 parent: 89308:cd23d0c3f850 parent: 89309:9aedb876c2d7 user: Zachary Ware date: Thu Feb 20 15:39:29 2014 -0600 summary: Issue #20221: Removed conflicting (or circular) hypot definition when compiled with VS 2010 or above. Initial patch by Tabrez Mohammed. files: Misc/NEWS | 3 +++ PC/pyconfig.h | 4 ++++ 2 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -103,6 +103,9 @@ Build ----- +- Issue #20221: Removed conflicting (or circular) hypot definition when + compiled with VS 2010 or above. Initial patch by Tabrez Mohammed. + - Issue #20609: Restored the ability to build 64-bit Windows binaries on 32-bit Windows, which was broken by the change in issue #19788. diff --git a/PC/pyconfig.h b/PC/pyconfig.h --- a/PC/pyconfig.h +++ b/PC/pyconfig.h @@ -207,7 +207,11 @@ #define Py_IS_INFINITY(X) (!_finite(X) && !_isnan(X)) #define Py_IS_FINITE(X) _finite(X) #define copysign _copysign + +/* VS 2010 and above already defines hypot as _hypot */ +#if _MSC_VER < 1600 #define hypot _hypot +#endif /* Side by Side assemblies supported in VS 2005 and VS 2008 but not 2010*/ #if _MSC_VER >= 1400 && _MSC_VER < 1600 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 20 23:26:37 2014 From: python-checkins at python.org (victor.stinner) Date: Thu, 20 Feb 2014 23:26:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Windows_buildbot=3A_use_--?= =?utf-8?q?timeout_feature_in_Tools/buildbot/test-amd64=2Ebat?= Message-ID: <3fVVlK1ys4z7LjN@mail.python.org> http://hg.python.org/cpython/rev/ad92e63de42c changeset: 89311:ad92e63de42c user: Victor Stinner date: Thu Feb 20 23:26:12 2014 +0100 summary: Windows buildbot: use --timeout feature in Tools/buildbot/test-amd64.bat Use the same default timeout than test.bat: 1 hour (3600 seconds). files: Tools/buildbot/test-amd64.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/buildbot/test-amd64.bat b/Tools/buildbot/test-amd64.bat --- a/Tools/buildbot/test-amd64.bat +++ b/Tools/buildbot/test-amd64.bat @@ -1,3 +1,3 @@ @rem Used by the buildbot "test" step. cd PCbuild -call rt.bat -d -q -x64 -uall -rwW -n %1 %2 %3 %4 %5 %6 %7 %8 %9 +call rt.bat -d -q -x64 -uall -rwW -n --timeout=3600 %1 %2 %3 %4 %5 %6 %7 %8 %9 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 21 01:56:12 2014 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 21 Feb 2014 01:56:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Two_wishes_were_fulfilled=2E?= Message-ID: <3fVZ3w3Gz8z7LkF@mail.python.org> http://hg.python.org/peps/rev/6663b3597adb changeset: 5376:6663b3597adb user: Guido van Rossum date: Thu Feb 20 16:55:12 2014 -0800 summary: Two wishes were fulfilled. files: pep-3156.txt | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/pep-3156.txt b/pep-3156.txt --- a/pep-3156.txt +++ b/pep-3156.txt @@ -1876,6 +1876,9 @@ - Support a "start TLS" operation to upgrade a TCP socket to SSL/TLS. +Former wish list items that have since been implemented (but aren't +specified by the PEP): + - UNIX domain sockets. - A per-loop error handling callback. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Feb 21 02:10:43 2014 From: python-checkins at python.org (yury.selivanov) Date: Fri, 21 Feb 2014 02:10:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=2Edocs=3A_Document?= =?utf-8?q?_subprocess=5Fexec_and_subprocess=5Fshell=2E_Issue_=2320694=2E?= Message-ID: <3fVZNg6CP9z7LkF@mail.python.org> http://hg.python.org/cpython/rev/ec3a70ef759d changeset: 89312:ec3a70ef759d user: Yury Selivanov date: Thu Feb 20 20:10:28 2014 -0500 summary: asyncio.docs: Document subprocess_exec and subprocess_shell. Issue #20694. files: Doc/library/asyncio-eventloop.rst | 52 +++++++++++++++++- 1 files changed, 48 insertions(+), 4 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -467,17 +467,61 @@ :class:`SelectSelector` or :class:`PollSelector` to handle character devices on Mac OS X 10.6 (Snow Leopard) and later. -.. method:: BaseEventLoop.subprocess_exec(protocol_factory, \*args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=False, shell=False, bufsize=0, \*\*kwargs) +.. method:: BaseEventLoop.subprocess_exec(protocol_factory, \*args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, \*\*kwargs) - XXX + Create a subprocess from one or more string arguments, where the first string + specifies the program to execute, and the remaining strings specify the + program's arguments. (Thus, together the string arguments form the + ``sys.argv`` value of the program, assuming it is a Python script.) This is + similar to the standard library :class:`subprocess.Popen` class called with + shell=False and the list of strings passed as the first argument; + however, where :class:`~subprocess.Popen` takes a single argument which is + list of strings, :func:`subprocess_exec` takes multiple string arguments. + + Other parameters: + + * *stdin*: Either a file-like object representing the pipe to be connected + to the subprocess's standard input stream using + :meth:`~BaseEventLoop.connect_write_pipe`, or the constant + :const:`subprocess.PIPE` (the default). By default a new pipe will be + created and connected. + + * *stdout*: Either a file-like object representing the pipe to be connected + to the subprocess's standard output stream using + :meth:`~BaseEventLoop.connect_write_pipe`, or the constant + :const:`subprocess.PIPE` (the default). By default a new pipe will be + created and connected. + + * *stderr*: Either a file-like object representing the pipe to be connected + to the subprocess's standard error stream using + :meth:`~BaseEventLoop.connect_read_pipe`, or one of the constants + :const:`subprocess.PIPE` (the default) or :const:`subprocess.STDOUT`. + By default a new pipe will be created and connected. When + :const:`subprocess.STDOUT` is specified, the subprocess's standard error + stream will be connected to the same pipe as the standard output stream. + + * All other keyword arguments are passed to :class:`subprocess.Popen` + without interpretation, except for *bufsize*, *universal_newlines* and + *shell*, which should not be specified at all. + + Returns a pair of ``(transport, protocol)``, where *transport* is an + instance of :class:`BaseSubprocessTransport`. This method is a :ref:`coroutine `. See the constructor of the :class:`subprocess.Popen` class for parameters. -.. method:: BaseEventLoop.subprocess_shell(protocol_factory, cmd, \*, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=False, shell=True, bufsize=0, \*\*kwargs) +.. method:: BaseEventLoop.subprocess_shell(protocol_factory, cmd, \*, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, \*\*kwargs) - XXX + Create a subprocess from *cmd*, which is a string using the platform's + "shell" syntax. This is similar to the standard library + :class:`subprocess.Popen` class called with ``shell=True``. + + See :meth:`~BaseEventLoop.subprocess_exec` for more details about + the remaining arguments. + + Returns a pair of ``(transport, protocol)``, where *transport* is an + instance of :class:`BaseSubprocessTransport`. This method is a :ref:`coroutine `. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 21 02:20:37 2014 From: python-checkins at python.org (yury.selivanov) Date: Fri, 21 Feb 2014 02:20:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_463_-_add_latest_changes_?= =?utf-8?q?by_Chris_Angelico=2E?= Message-ID: <3fVZc54GcZz7LkB@mail.python.org> http://hg.python.org/peps/rev/4fb38d97be5e changeset: 5377:4fb38d97be5e user: Yury Selivanov date: Thu Feb 20 20:20:25 2014 -0500 summary: PEP 463 - add latest changes by Chris Angelico. files: pep-0463.txt | 776 ++++++++++++++++++++++++++++---------- 1 files changed, 573 insertions(+), 203 deletions(-) diff --git a/pep-0463.txt b/pep-0463.txt --- a/pep-0463.txt +++ b/pep-0463.txt @@ -46,12 +46,6 @@ * statistics.mean(data) - no way to handle an empty iterator -Additionally, this syntax would allow a convenient way to capture -exceptions in interactive Python; returned values are captured by "_", -but exceptions currently are not. This could be spelled: - ->>> expr except Exception as e: e - Rationale ========= @@ -69,15 +63,24 @@ default: it simply raises an appropriate exception, and the caller catches it. +With some situations, an LBYL technique can be used (checking if some +sequence has enough length before indexing into it, for instance). This is +not safe in all cases, but as it is often convenient, programmers will be +tempted to sacrifice the safety of EAFP in favour of the notational brevity +of LBYL. Additionally, some LBYL techniques (eg involving getattr with +three arguments) warp the code into looking like literal strings rather +than attribute lookup, which can impact readability. A convenient EAFP +notation solves all of this. + There's no convenient way to write a helper function to do this; the nearest is something ugly using either lambda:: def except_(expression, exception_list, default): try: return expression() - except exception_list as e: - return default(e) - value = except_(lambda: 1/x, ZeroDivisionError, lambda e: float("nan")) + except exception_list: + return default() + value = except_(lambda: 1/x, ZeroDivisionError, lambda: float("nan")) which is clunky, and unable to handle multiple exception clauses; or eval:: @@ -132,44 +135,441 @@ Specifically, the syntax proposed is:: - expr except exc [as e]: default [except exc2 [as e]: default2] ... + expr except exception_list: default -where expr, exc, and default are all expressions. First, expr is -evaluated. If no exception is raised, its value is the value of the -overall expression. If any exception is raised, exc is evaluated, and -should result in either a type or a tuple, just as with the statement -form of try/except. Any matching exception will result in the -corresponding default expression being evaluated and becoming the -value of the expression. As with the statement form of try/ except, -subsequent except clauses will be checked if the first one does not -match, and if none match, the raised exception will propagate upward. -Also as with the try/except statement, the keyword 'as' can be used to -bind the exception object to a local name. +where expr, exception_list, and default are all expressions. First, +expr is evaluated. If no exception is raised, its value is the value +of the overall expression. If any exception is raised, exception_list +is evaluated, and should result in either a type or a tuple, just as +with the statement form of try/except. Any matching exception will +result in the corresponding default expression being evaluated and +becoming the value of the expression. As with the statement form of +try/except, non-matching exceptions will propagate upward. -Omitting the exception list should be legal, just as with the -statement form of try/except, though this should of course be -discouraged by PEP 8. - -The exception object can be captured just as in a normal try/except -block:: - - # Return the next yielded or returned value from a generator - value = next(it) except StopIteration as e: e.args[0] - -This is effectively equivalent to:: - - try: - _ = next(it) - except StopIteration as e: - _ = e.args[0] - value = _ +Note that the current proposal does not allow the exception object to +be captured. Where this is needed, the statement form must be used. +(See below for discussion and elaboration on this.) This ternary operator would be between lambda and if/else in precedence. +Consider this example of a two-level cache:: + for key in sequence: + x = (lvl1[key] except KeyError: (lvl2[key] except KeyError: f(key))) + # do something with x -Chaining --------- +This cannot be rewritten as:: + x = lvl1.get(key, lvl2.get(key, f(key))) + +which, despite being shorter, defeats the purpose of the cache, as it must +calculate a default value to pass to get(). The .get() version calculates +backwards; the exception-testing version calculates forwards, as would be +expected. The nearest useful equivalent would be:: + x = lvl1.get(key) or lvl2.get(key) or f(key) +which depends on the values being nonzero, as well as depending on the cache +object supporting this functionality. + + +Alternative Proposals +===================== + +Discussion on python-ideas brought up the following syntax suggestions:: + + value = expr except default if Exception [as e] + value = expr except default for Exception [as e] + value = expr except default from Exception [as e] + value = expr except Exception [as e] return default + value = expr except (Exception [as e]: default) + value = expr except Exception [as e] try default + value = expr except Exception [as e] continue with default + value = default except Exception [as e] else expr + value = try expr except Exception [as e]: default + value = expr except default # Catches anything + value = expr except(Exception) default # Catches only the named type(s) + value = default if expr raise Exception + value = expr or else default if Exception + value = expr except Exception [as e] -> default + value = expr except Exception [as e] pass default + +It has also been suggested that a new keyword be created, rather than +reusing an existing one. Such proposals fall into the same structure +as the last form, but with a different keyword in place of 'pass'. +Suggestions include 'then', 'when', and 'use'. Also, in the context of +the "default if expr raise Exception" proposal, it was suggested that a +new keyword "raises" be used. + +All forms involving the 'as' capturing clause have been deferred from +this proposal in the interests of simplicity, but are preserved in the +table above as an accurate record of suggestions. + + +Open Issues +=========== + +Parentheses around the entire expression +---------------------------------------- + +Generator expressions require parentheses, unless they would be +strictly redundant. Ambiguities with except expressions could be +resolved in the same way, forcing nested except-in-except trees to be +correctly parenthesized and requiring that the outer expression be +clearly delineated. `Steven D'Aprano elaborates on the issue.`__ + +__ https://mail.python.org/pipermail/python-ideas/2014-February/025647.html + + +Example usage +============= + +For each example, an approximately-equivalent statement form is given, +to show how the expression will be parsed. These are not always +strictly equivalent, but will accomplish the same purpose. It is NOT +safe for the interpreter to translate one into the other. + +A number of these examples are taken directly from the Python standard +library, with file names and line numbers correct as of early Feb 2014. +Many of these patterns are extremely common. + +Retrieve an argument, defaulting to None:: + cond = args[1] except IndexError: None + + # Lib/pdb.py:803: + try: + cond = args[1] + except IndexError: + cond = None + +Fetch information from the system if available:: + pwd = os.getcwd() except OSError: None + + # Lib/tkinter/filedialog.py:210: + try: + pwd = os.getcwd() + except OSError: + pwd = None + +Attempt a translation, falling back on the original:: + e.widget = self._nametowidget(W) except KeyError: W + + # Lib/tkinter/__init__.py:1222: + try: + e.widget = self._nametowidget(W) + except KeyError: + e.widget = W + +Read from an iterator, continuing with blank lines once it's +exhausted:: + line = readline() except StopIteration: '' + + # Lib/lib2to3/pgen2/tokenize.py:370: + try: + line = readline() + except StopIteration: + line = '' + +Retrieve platform-specific information (note the DRY improvement); +this particular example could be taken further, turning a series of +separate assignments into a single large dict initialization:: + # sys.abiflags may not be defined on all platforms. + _CONFIG_VARS['abiflags'] = sys.abiflags except AttributeError: '' + + # Lib/sysconfig.py:529: + try: + _CONFIG_VARS['abiflags'] = sys.abiflags + except AttributeError: + # sys.abiflags may not be defined on all platforms. + _CONFIG_VARS['abiflags'] = '' + +Retrieve an indexed item, defaulting to None (similar to dict.get):: + def getNamedItem(self, name): + return self._attrs[name] except KeyError: None + + # Lib/xml/dom/minidom.py:573: + def getNamedItem(self, name): + try: + return self._attrs[name] + except KeyError: + return None + + +Translate numbers to names, falling back on the numbers:: + g = grp.getgrnam(tarinfo.gname)[2] except KeyError: tarinfo.gid + u = pwd.getpwnam(tarinfo.uname)[2] except KeyError: tarinfo.uid + + # Lib/tarfile.py:2198: + try: + g = grp.getgrnam(tarinfo.gname)[2] + except KeyError: + g = tarinfo.gid + try: + u = pwd.getpwnam(tarinfo.uname)[2] + except KeyError: + u = tarinfo.uid + +Perform some lengthy calculations in EAFP mode, handling division by +zero as a sort of sticky NaN:: + + value = calculate(x) except ZeroDivisionError: float("nan") + + try: + value = calculate(x) + except ZeroDivisionError: + value = float("nan") + +Calculate the mean of a series of numbers, falling back on zero:: + + value = statistics.mean(lst) except statistics.StatisticsError: 0 + + try: + value = statistics.mean(lst) + except statistics.StatisticsError: + value = 0 + +Retrieving a message from either a cache or the internet, with auth +check:: + + logging.info("Message shown to user: %s",((cache[k] + except LookupError: + (backend.read(k) except OSError: 'Resource not available') + ) + if check_permission(k) else 'Access denied' + ) except BaseException: "This is like a bare except clause") + + try: + if check_permission(k): + try: + _ = cache[k] + except LookupError: + try: + _ = backend.read(k) + except OSError: + _ = 'Resource not available' + else: + _ = 'Access denied' + except BaseException: + _ = "This is like a bare except clause" + logging.info("Message shown to user: %s", _) + +Looking up objects in a sparse list of overrides:: + + (overrides[x] or default except IndexError: default).ping() + + try: + (overrides[x] or default).ping() + except IndexError: + default.ping() + + +Narrowing of exception-catching scope +------------------------------------- + +The following examples, taken directly from Python's standard library, +demonstrate how the scope of the try/except can be conveniently narrowed. +To do this with the statement form of try/except would require a temporary +variable, but it's far cleaner as an expression. + +Lib/ipaddress.py:343:: + try: + ips.append(ip.ip) + except AttributeError: + ips.append(ip.network_address) +Becomes:: + ips.append(ip.ip except AttributeError: ip.network_address) +The expression form is nearly equivalent to this:: + try: + _ = ip.ip + except AttributeError: + _ = ip.network_address + ips.append(_) + +Lib/tempfile.py:130:: + try: + dirlist.append(_os.getcwd()) + except (AttributeError, OSError): + dirlist.append(_os.curdir) +Becomes:: + dirlist.append(_os.getcwd() except (AttributeError, OSError): _os.curdir) + +Lib/asyncore.py:264:: + try: + status.append('%s:%d' % self.addr) + except TypeError: + status.append(repr(self.addr)) +Becomes:: + status.append('%s:%d' % self.addr except TypeError: repr(self.addr)) + + +Comparisons with other languages +================================ + +(With thanks to Andrew Barnert for compiling this section.) + +`Ruby's`__ "begin?rescue?rescue?else?ensure?end" is an expression +(potentially with statements inside it). It has the equivalent of an "as" +clause, and the equivalent of bare except. And it uses no punctuation or +keyword between the bare except/exception class/exception class with as +clause and the value. (And yes, it's ambiguous unless you understand +Ruby's statement/expression rules.) + +__ http://www.skorks.com/2009/09/ruby-exceptions-and-exception-handling/ + +:: + + x = begin computation() rescue MyException => e default(e) end; + x = begin computation() rescue MyException default() end; + x = begin computation() rescue default() end; + x = begin computation() rescue MyException default() rescue OtherException other() end; + +In terms of this PEP:: + + x = computation() except MyException as e default(e) + x = computation() except MyException default(e) + x = computation() except default(e) + x = computation() except MyException default() except OtherException other() + +`Erlang`__ has a try expression that looks like this:: + +__ http://erlang.org/doc/reference_manual/expressions.html#id79284 + + x = try computation() catch MyException:e -> default(e) end; + x = try computation() catch MyException:e -> default(e); OtherException:e -> other(e) end; + +The class and "as" name are mandatory, but you can use "_" for either. +There's also an optional "when" guard on each, and a "throw" clause that +you can catch, which I won't get into. To handle multiple exceptions, +you just separate the clauses with semicolons, which I guess would map +to commas in Python. So:: + + x = try computation() except MyException as e -> default(e) + x = try computation() except MyException as e -> default(e), OtherException as e->other_default(e) + +Erlang also has a "catch" expression, which, despite using the same keyword, +is completely different, and you don't want to know about it. + + +The ML family has two different ways of dealing with this, "handle" and +"try"; the difference between the two is that "try" pattern-matches the +exception, which gives you the effect of multiple except clauses and as +clauses. In either form, the handler clause is punctuated by "=>" in +some dialects, "->" in others. + +To avoid confusion, I'll write the function calls in Python style. + +Here's `SML's`__ "handle":: +__ http://www.cs.cmu.edu/~rwh/introsml/core/exceptions.htm + + let x = computation() handle MyException => default();; + +Here's `OCaml's`__ "try":: +__ http://www2.lib.uchicago.edu/keith/ocaml-class/exceptions.html + + let x = try computation() with MyException explanation -> default(explanation);; + + let x = try computation() with + + MyException(e) -> default(e) + | MyOtherException() -> other_default() + | (e) -> fallback(e);; + +In terms of this PEP, these would be something like:: + + x = computation() except MyException => default() + x = try computation() except MyException e -> default() + x = (try computation() + except MyException as e -> default(e) + except MyOtherException -> other_default() + except BaseException as e -> fallback(e)) + +Many ML-inspired but not-directly-related languages from academia mix things +up, usually using more keywords and fewer symbols. So, the `Oz`__ would map +to Python as:: +__ http://mozart.github.io/mozart-v1/doc-1.4.0/tutorial/node5.html + + x = try computation() catch MyException as e then default(e) + + +Many Lisp-derived languages, like `Clojure,`__ implement try/catch as special +forms (if you don't know what that means, think function-like macros), so you +write, effectively:: +__ http://clojure.org/special_forms#Special%20Forms--(try%20expr*%20catch-clause*%20finally-clause?) + + try(computation(), catch(MyException, explanation, default(explanation))) + + try(computation(), + catch(MyException, explanation, default(explanation)), + catch(MyOtherException, explanation, other_default(explanation))) + +In Common Lisp, this is done with a slightly clunkier `"handler-case" macro,`__ +but the basic idea is the same. + +__ http://clhs.lisp.se/Body/m_hand_1.htm + + +The Lisp style is, surprisingly, used by some languages that don't have +macros, like Lua, where `xpcall`__ takes functions. Writing lambdas +Python-style instead of Lua-style:: +__ http://www.gammon.com.au/scripts/doc.php?lua=xpcall + + x = xpcall(lambda: expression(), lambda e: default(e)) + +This actually returns (true, expression()) or (false, default(e)), but I think we can ignore that part. + + +Haskell is actually similar to Lua here (except that it's all done +with monads, of course):: + + x = do catch(lambda: expression(), lambda e: default(e)) + +You can write a pattern matching expression within the function to decide +what to do with it; catching and re-raising exceptions you don't want is +cheap enough to be idiomatic. + +But Haskell infixing makes this nicer:: + + x = do expression() `catch` lambda: default() + x = do expression() `catch` lambda e: default(e) + +And that makes the parallel between the lambda colon and the except +colon in the proposal much more obvious:: + + + x = expression() except Exception: default() + x = expression() except Exception as e: default(e) + + +`Tcl`__ has the other half of Lua's xpcall; catch is a function which returns +true if an exception was caught, false otherwise, and you get the value out +in other ways. And it's all built around the the implicit quote-and-exec +that everything in Tcl is based on, making it even harder to describe in +Python terms than Lisp macros, but something like:: +__ http://wiki.tcl.tk/902 + + if {[ catch("computation()") "explanation"]} { default(explanation) } + + +`Smalltalk`__ is also somewhat hard to map to Python. The basic version +would be:: +__ http://smalltalk.gnu.org/wiki/exceptions + + x := computation() on:MyException do:default() + +? but that's basically Smalltalk's passing-arguments-with-colons +syntax, not its exception-handling syntax. + + +Deferred sub-proposals +====================== + +Multiple except clauses +----------------------- + +An examination of use-cases shows that this is not needed as often as +it would be with the statement form, and as its syntax is a point on +which consensus has not been reached, the entire feature is deferred. + +In order to ensure compatibility with future versions, ensure that any +consecutive except operators are parenthesized to guarantee the +interpretation you expect. Multiple 'except' keywords can be used, and they will all catch exceptions raised in the original expression (only):: @@ -200,47 +600,8 @@ ternary-except; ternary-except is an expression; therefore you can put a ternary-except inside a ternary-except. - -Alternative Proposals -===================== - -Discussion on python-ideas brought up the following syntax suggestions:: - - value = expr except default if Exception [as e] - value = expr except default for Exception [as e] - value = expr except default from Exception [as e] - value = expr except Exception [as e] return default - value = expr except (Exception [as e]: default) - value = expr except Exception [as e] try default - value = expr except Exception [as e] continue with default - value = default except Exception [as e] else expr - value = try expr except Exception [as e]: default - value = expr except Exception [as e] pass default - -It has also been suggested that a new keyword be created, rather than -reusing an existing one. Such proposals fall into the same structure -as the last form, but with a different keyword in place of 'pass'. -Suggestions include 'then', 'when', and 'use'. - -Additionally, the following has been suggested as a similar -short-hand, though not technically an expression:: - - statement except Exception: pass - - try: - statement - except Exception: - pass - - -Open Issues -=========== - -Commas between multiple except clauses --------------------------------------- - -Where there are multiple except clauses, should they be separated by -commas? It may be easier for the parser, that way:: +Open question: Where there are multiple except clauses, should they be +separated by commas? It may be easier for the parser, that way:: value = (expr except Exception1 [as e]: default1, @@ -269,16 +630,113 @@ the expression's meaning. -Parentheses around the entire expression ----------------------------------------- +Capturing the exception object +------------------------------ -Generator expressions require parentheses, unless they would be -strictly redundant. Ambiguities with except expressions could be -resolved in the same way, forcing nested except-in-except trees to be -correctly parenthesized and requiring that the outer expression be -clearly delineated. `Steven D'Aprano elaborates on the issue.`__ +In a try/except block, the use of 'as' to capture the exception object +creates a local name binding, and implicitly deletes that binding in a +finally clause. As 'finally' is not a part of this proposal (see +below), this makes it tricky to describe; also, this use of 'as' gives +a way to create a name binding in an expression context. Should the +default clause have an inner scope in which the name exists, shadowing +anything of the same name elsewhere? Should it behave the same way the +statement try/except does, and unbind the name? Should it bind the +name and leave it bound? (Almost certainly not; this behaviour was +changed in Python 3 for good reason.) -__ https://mail.python.org/pipermail/python-ideas/2014-February/025647.html +Additionally, this syntax would allow a convenient way to capture +exceptions in interactive Python; returned values are captured by "_", +but exceptions currently are not. This could be spelled: + +>>> expr except Exception as e: e + +(The inner scope idea is tempting, but currently CPython handles list +comprehensions with a nested function call, as this is considered +easier. It may be of value to simplify both comprehensions and except +expressions, but that is a completely separate proposal to this PEP; +alternatively, it may be better to stick with what's known to +work. `Nick Coghlan elaborates.`__) + +__ https://mail.python.org/pipermail/python-ideas/2014-February/025702.html + +An examination of the Python standard library shows that, while the use +of 'as' is fairly common (occurring in roughly one except clause in five), +it is extremely *uncommon* in the cases which could logically be converted +into the expression form. Its few uses can simply be left unchanged. +Consequently, in the interests of simplicity, the 'as' clause is not +included in this proposal. A subsequent Python version can add this without +breaking any existing code, as 'as' is already a keyword. + +One example where this could possibly be useful is Lib/imaplib.py:568:: + try: typ, dat = self._simple_command('LOGOUT') + except: typ, dat = 'NO', ['%s: %s' % sys.exc_info()[:2]] +This could become:: + typ, dat = (self._simple_command('LOGOUT') + except BaseException as e: ('NO', '%s: %s' % (type(e), e))) +Or perhaps some other variation. This is hardly the most compelling use-case, +but an intelligent look at this code could tidy it up significantly. In the +absence of further examples showing any need of the exception object, I have +opted to defer indefinitely the recommendation. + + +Rejected sub-proposals +====================== + +finally clause +-------------- +The statement form try... finally or try... except... finally has no +logical corresponding expression form. Therefore the finally keyword +is not a part of this proposal, in any way. + + +Bare except having different meaning +------------------------------------ + +With several of the proposed syntaxes, omitting the exception type name +would be easy and concise, and would be tempting. For convenience's sake, +it might be advantageous to have a bare 'except' clause mean something +more useful than "except BaseException". Proposals included having it +catch Exception, or some specific set of "common exceptions" (subclasses +of a new type called ExpressionError), or have it look for a tuple named +ExpressionError in the current scope, with a built-in default such as +(ValueError, UnicodeError, AttributeError, EOFError, IOError, OSError, +LookupError, NameError, ZeroDivisionError). All of these were rejected, +for severa reasons. + +* First and foremost, consistency with the statement form of try/except +would be broken. Just as a list comprehension or ternary if expression +can be explained by "breaking it out" into its vertical statement form, +an expression-except should be able to be explained by a relatively +mechanical translation into a near-equivalent statement. Any form of +syntax common to both should therefore have the same semantics in each, +and above all should not have the subtle difference of catching more in +one than the other, as it will tend to attract unnoticed bugs. + +* Secondly, the set of appropriate exceptions to catch would itself be +a huge point of contention. It would be impossible to predict exactly +which exceptions would "make sense" to be caught; why bless some of them +with convenient syntax and not others? + +* And finally (this partly because the recommendation was that a bare +except should be actively encouraged, once it was reduced to a "reasonable" +set of exceptions), any situation where you catch an exception you don't +expect to catch is an unnecessary bug magnet. + +Consequently, the use of a bare 'except' is down to two possibilities: +either it is syntactically forbidden in the expression form, or it is +permitted with the exact same semantics as in the statement form (namely, +that it catch BaseException and be unable to capture it with 'as'). + + +Bare except clauses +------------------- + +PEP 8 rightly advises against the use of a bare 'except'. While it is +syntactically legal in a statement, and for backward compatibility must +remain so, there is little value in encouraging its use. In an expression +except clause, "except:" is a SyntaxError; use the equivalent long-hand +form "except BaseException:" instead. A future version of Python MAY choose +to reinstate this, which can be done without breaking compatibility. Parentheses around the except clauses @@ -293,130 +751,42 @@ # ... except ExceptionN [as e]: defaultN ) +This is more compelling when one or both of the deferred sub-proposals +of multiple except clauses and/or exception capturing is included. In +their absence, the parentheses would be thus:: + value = expr except ExceptionType: default + value = expr (except ExceptionType: default) -Scope of default expressions and 'as' -------------------------------------- +The advantage is minimal, and the potential to confuse a reader into +thinking the except clause is separate from the expression, or into thinking +this is a function call, makes this non-compelling. The expression can, of +course, be parenthesized if desired, as can the default:: + value = (expr) except ExceptionType: (default) -In a try/except block, the use of 'as' to capture the exception object -creates a local name binding, and implicitly deletes that binding in a -finally clause. As 'finally' is not a part of this proposal (see -below), this makes it tricky to describe; also, this use of 'as' gives -a way to create a name binding in an expression context. Should the -default clause have an inner scope in which the name exists, shadowing -anything of the same name elsewhere? Should it behave the same way the -statement try/except does, and unbind the name? Should it bind the -name and leave it bound? (Almost certainly not; this behaviour was -changed in Python 3 for good reason.) -(The inner scope idea is tempting, but currently CPython handles list -comprehensions with a nested function call, as this is considered -easier. It may be of value to simplify both comprehensions and except -expressions, but that is a completely separate proposal to this PEP; -alternatively, it may be better to stick with what's known to -work. `Nick Coghlan elaborates.`__) +Short-hand for "except: pass" +----------------------------- -__ https://mail.python.org/pipermail/python-ideas/2014-February/025702.html +The following was been suggested as a similar +short-hand, though not technically an expression:: - -Example usage -============= - -For each example, an approximately-equivalent statement form is given, -to show how the expression will be parsed. These are not always -strictly equivalent, but will accomplish the same purpose. It is NOT -safe for the interpreter to translate one into the other. - -Perform some lengthy calculations in EAFP mode, handling division by -zero as a sort of sticky NaN:: - - value = calculate(x) except ZeroDivisionError: float("nan") + statement except Exception: pass try: - value = calculate(x) - except ZeroDivisionError: - value = float("nan") + statement + except Exception: + pass -Retrieving from a generator, either the next yielded value or the -returned, and coping with the absence of such a return value:: +For instance, a common use-case is attempting the removal of a file:: + os.unlink(some_file) except OSError: pass - value = (next(it) - except StopIteration as e: - (e.args[0] except IndexError: None) - ) +There is an equivalent already in Python 3.4, however, in contextlib:: + from contextlib import suppress + with suppress(OSError): os.unlink(some_file) - try: - value = next(it) - except StopIteration as e: - try: - value = e.args[0] - except IndexError: - value = None - -Calculate the mean of a series of numbers, falling back on zero:: - - value = statistics.mean(lst) except statistics.StatisticsError: 0 - - try: - value = statistics.mean(lst) - except statistics.StatisticsError: - value = 0 - -Set a PyGTK label to a human-readable result from fetching a URL:: - - display.set_text( - urllib.request.urlopen(url) - except urllib.error.HTTPError as e: "Error %d: %s"%(x.getcode(), x.msg) - except (ValueError, urllib.error.URLError) as e: "Invalid URL: "+str(e) - ) - - try: - display.set_text(urllib.request.urlopen(url)) - except urllib.error.HTTPError as e: - display.set_text("Error %d: %s"%(x.getcode(), x.msg)) - except (ValueError, urllib.error.URLError) as e: - display.set_text("Invalid URL: "+str(e)) - -Retrieving a message from either a cache or the internet,with auth -check:: - - logging.info("Message shown to user: %s",((cache[k] - except LookupError: - (backend.read(k) except OSError: 'Resource not available') - ) - if check_permission(k) else 'Access denied' - ) except: "I'm an idiot and using a bare except clause") - - try: - if check_permission(k): - try: - _ = cache[k] - except LookupError: - try: - _ = backend.read(k) - except OSError: - _ = 'Resource not available' - else: - _ = 'Access denied' - except: - _ = "I'm an idiot and using a bare except clause" - logging.info("Message shown to user: %s", _) - -Looking up objects in a sparse list of overrides:: - - (overrides[x] or default except IndexError: default).ping() - - try: - (overrides[x] or default).ping() - except IndexError: - default.ping() - - -Rejected sub-proposals -====================== - -The statement form try... finally or try... except... finally has no -logical corresponding expression form. Therefore the finally keyword -is not a part of this proposal, in any way. +As this is already a single line (or two with a break after the colon), +there is little need of new syntax and a confusion of statement vs +expression to achieve this. Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Feb 21 02:53:37 2014 From: python-checkins at python.org (donald.stufft) Date: Fri, 21 Feb 2014 02:53:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Upgrade_pip_from_1=2E5=2E2?= =?utf-8?b?IHRvIDEuNS4z?= Message-ID: <3fVbL90HTNz7LjN@mail.python.org> http://hg.python.org/cpython/rev/d57df3f72715 changeset: 89313:d57df3f72715 user: Donald Stufft date: Thu Feb 20 20:53:27 2014 -0500 summary: Upgrade pip from 1.5.2 to 1.5.3 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/pip-1.5.2-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-1.5.3-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -10,7 +10,7 @@ _SETUPTOOLS_VERSION = "2.1" -_PIP_VERSION = "1.5.2" +_PIP_VERSION = "1.5.3" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-1.5.2-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-1.5.2-py2.py3-none-any.whl deleted file mode 100644 index 9133eed9718ca6849514fa8a0b874fcc05050913..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-1.5.3-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-1.5.3-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..31cee0aea7ef59dc070f3a7845c09699e95a97e8 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 21 05:33:50 2014 From: python-checkins at python.org (yury.selivanov) Date: Fri, 21 Feb 2014 05:33:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_463=3A_Update_post_histor?= =?utf-8?q?y?= Message-ID: <3fVfv22hqLz7LjN@mail.python.org> http://hg.python.org/peps/rev/eb7e116cbb70 changeset: 5378:eb7e116cbb70 user: Yury Selivanov date: Thu Feb 20 23:33:43 2014 -0500 summary: PEP 463: Update post history files: pep-0463.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0463.txt b/pep-0463.txt --- a/pep-0463.txt +++ b/pep-0463.txt @@ -8,7 +8,7 @@ Content-Type: text/x-rst Created: 15-Feb-2014 Python-Version: 3.5 -Post-History: 16-Feb-2014 +Post-History: 20-Feb-2014, 16-Feb-2014 Abstract -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Feb 21 05:45:04 2014 From: python-checkins at python.org (yury.selivanov) Date: Fri, 21 Feb 2014 05:45:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_463=3A_Fix_some_ReST_warn?= =?utf-8?q?ings_=26_errors?= Message-ID: <3fVg806nYjz7LlD@mail.python.org> http://hg.python.org/peps/rev/ce125a2c6047 changeset: 5379:ce125a2c6047 user: Yury Selivanov date: Thu Feb 20 23:44:58 2014 -0500 summary: PEP 463: Fix some ReST warnings & errors files: pep-0463.txt | 206 ++++++++++++++++++++++++-------------- 1 files changed, 129 insertions(+), 77 deletions(-) diff --git a/pep-0463.txt b/pep-0463.txt --- a/pep-0463.txt +++ b/pep-0463.txt @@ -154,18 +154,22 @@ precedence. Consider this example of a two-level cache:: + for key in sequence: x = (lvl1[key] except KeyError: (lvl2[key] except KeyError: f(key))) # do something with x This cannot be rewritten as:: - x = lvl1.get(key, lvl2.get(key, f(key))) + + x = lvl1.get(key, lvl2.get(key, f(key))) which, despite being shorter, defeats the purpose of the cache, as it must calculate a default value to pass to get(). The .get() version calculates backwards; the exception-testing version calculates forwards, as would be expected. The nearest useful equivalent would be:: - x = lvl1.get(key) or lvl2.get(key) or f(key) + + x = lvl1.get(key) or lvl2.get(key) or f(key) + which depends on the values being nonzero, as well as depending on the cache object supporting this functionality. @@ -231,56 +235,62 @@ Many of these patterns are extremely common. Retrieve an argument, defaulting to None:: - cond = args[1] except IndexError: None - # Lib/pdb.py:803: - try: - cond = args[1] - except IndexError: - cond = None + cond = args[1] except IndexError: None + + # Lib/pdb.py:803: + try: + cond = args[1] + except IndexError: + cond = None Fetch information from the system if available:: - pwd = os.getcwd() except OSError: None - # Lib/tkinter/filedialog.py:210: - try: - pwd = os.getcwd() - except OSError: - pwd = None + pwd = os.getcwd() except OSError: None + + # Lib/tkinter/filedialog.py:210: + try: + pwd = os.getcwd() + except OSError: + pwd = None Attempt a translation, falling back on the original:: - e.widget = self._nametowidget(W) except KeyError: W - # Lib/tkinter/__init__.py:1222: - try: - e.widget = self._nametowidget(W) - except KeyError: - e.widget = W + e.widget = self._nametowidget(W) except KeyError: W + + # Lib/tkinter/__init__.py:1222: + try: + e.widget = self._nametowidget(W) + except KeyError: + e.widget = W Read from an iterator, continuing with blank lines once it's exhausted:: - line = readline() except StopIteration: '' - # Lib/lib2to3/pgen2/tokenize.py:370: - try: - line = readline() - except StopIteration: - line = '' + line = readline() except StopIteration: '' + + # Lib/lib2to3/pgen2/tokenize.py:370: + try: + line = readline() + except StopIteration: + line = '' Retrieve platform-specific information (note the DRY improvement); this particular example could be taken further, turning a series of separate assignments into a single large dict initialization:: + + # sys.abiflags may not be defined on all platforms. + _CONFIG_VARS['abiflags'] = sys.abiflags except AttributeError: '' + + # Lib/sysconfig.py:529: + try: + _CONFIG_VARS['abiflags'] = sys.abiflags + except AttributeError: # sys.abiflags may not be defined on all platforms. - _CONFIG_VARS['abiflags'] = sys.abiflags except AttributeError: '' - - # Lib/sysconfig.py:529: - try: - _CONFIG_VARS['abiflags'] = sys.abiflags - except AttributeError: - # sys.abiflags may not be defined on all platforms. - _CONFIG_VARS['abiflags'] = '' + _CONFIG_VARS['abiflags'] = '' Retrieve an indexed item, defaulting to None (similar to dict.get):: + def getNamedItem(self, name): return self._attrs[name] except KeyError: None @@ -291,20 +301,20 @@ except KeyError: return None +Translate numbers to names, falling back on the numbers:: -Translate numbers to names, falling back on the numbers:: - g = grp.getgrnam(tarinfo.gname)[2] except KeyError: tarinfo.gid - u = pwd.getpwnam(tarinfo.uname)[2] except KeyError: tarinfo.uid + g = grp.getgrnam(tarinfo.gname)[2] except KeyError: tarinfo.gid + u = pwd.getpwnam(tarinfo.uname)[2] except KeyError: tarinfo.uid - # Lib/tarfile.py:2198: - try: - g = grp.getgrnam(tarinfo.gname)[2] - except KeyError: - g = tarinfo.gid - try: - u = pwd.getpwnam(tarinfo.uname)[2] - except KeyError: - u = tarinfo.uid + # Lib/tarfile.py:2198: + try: + g = grp.getgrnam(tarinfo.gname)[2] + except KeyError: + g = tarinfo.gid + try: + u = pwd.getpwnam(tarinfo.uname)[2] + except KeyError: + u = tarinfo.uid Perform some lengthy calculations in EAFP mode, handling division by zero as a sort of sticky NaN:: @@ -369,34 +379,45 @@ variable, but it's far cleaner as an expression. Lib/ipaddress.py:343:: - try: - ips.append(ip.ip) - except AttributeError: - ips.append(ip.network_address) + + try: + ips.append(ip.ip) + except AttributeError: + ips.append(ip.network_address) + Becomes:: - ips.append(ip.ip except AttributeError: ip.network_address) + + ips.append(ip.ip except AttributeError: ip.network_address) + The expression form is nearly equivalent to this:: - try: - _ = ip.ip - except AttributeError: - _ = ip.network_address - ips.append(_) + + try: + _ = ip.ip + except AttributeError: + _ = ip.network_address + ips.append(_) Lib/tempfile.py:130:: + try: dirlist.append(_os.getcwd()) except (AttributeError, OSError): dirlist.append(_os.curdir) + Becomes:: + dirlist.append(_os.getcwd() except (AttributeError, OSError): _os.curdir) Lib/asyncore.py:264:: - try: - status.append('%s:%d' % self.addr) - except TypeError: - status.append(repr(self.addr)) + + try: + status.append('%s:%d' % self.addr) + except TypeError: + status.append(repr(self.addr)) + Becomes:: - status.append('%s:%d' % self.addr except TypeError: repr(self.addr)) + + status.append('%s:%d' % self.addr except TypeError: repr(self.addr)) Comparisons with other languages @@ -427,10 +448,12 @@ x = computation() except default(e) x = computation() except MyException default() except OtherException other() -`Erlang`__ has a try expression that looks like this:: +`Erlang`__ has a try expression that looks like this __ http://erlang.org/doc/reference_manual/expressions.html#id79284 +:: + x = try computation() catch MyException:e -> default(e) end; x = try computation() catch MyException:e -> default(e); OtherException:e -> other(e) end; @@ -455,14 +478,20 @@ To avoid confusion, I'll write the function calls in Python style. -Here's `SML's`__ "handle":: +Here's `SML's`__ "handle" + __ http://www.cs.cmu.edu/~rwh/introsml/core/exceptions.htm +:: + let x = computation() handle MyException => default();; -Here's `OCaml's`__ "try":: +Here's `OCaml's`__ "try" + __ http://www2.lib.uchicago.edu/keith/ocaml-class/exceptions.html +:: + let x = try computation() with MyException explanation -> default(explanation);; let x = try computation() with @@ -482,17 +511,23 @@ Many ML-inspired but not-directly-related languages from academia mix things up, usually using more keywords and fewer symbols. So, the `Oz`__ would map -to Python as:: +to Python as + __ http://mozart.github.io/mozart-v1/doc-1.4.0/tutorial/node5.html +:: + x = try computation() catch MyException as e then default(e) Many Lisp-derived languages, like `Clojure,`__ implement try/catch as special forms (if you don't know what that means, think function-like macros), so you -write, effectively:: +write, effectively + __ http://clojure.org/special_forms#Special%20Forms--(try%20expr*%20catch-clause*%20finally-clause?) +:: + try(computation(), catch(MyException, explanation, default(explanation))) try(computation(), @@ -507,9 +542,12 @@ The Lisp style is, surprisingly, used by some languages that don't have macros, like Lua, where `xpcall`__ takes functions. Writing lambdas -Python-style instead of Lua-style:: +Python-style instead of Lua-style + __ http://www.gammon.com.au/scripts/doc.php?lua=xpcall +:: + x = xpcall(lambda: expression(), lambda e: default(e)) This actually returns (true, expression()) or (false, default(e)), but I think we can ignore that part. @@ -541,19 +579,25 @@ true if an exception was caught, false otherwise, and you get the value out in other ways. And it's all built around the the implicit quote-and-exec that everything in Tcl is based on, making it even harder to describe in -Python terms than Lisp macros, but something like:: +Python terms than Lisp macros, but something like + __ http://wiki.tcl.tk/902 +:: + if {[ catch("computation()") "explanation"]} { default(explanation) } `Smalltalk`__ is also somewhat hard to map to Python. The basic version -would be:: +would be + __ http://smalltalk.gnu.org/wiki/exceptions +:: + x := computation() on:MyException do:default() -? but that's basically Smalltalk's passing-arguments-with-colons +... but that's basically Smalltalk's passing-arguments-with-colons syntax, not its exception-handling syntax. @@ -646,9 +690,9 @@ Additionally, this syntax would allow a convenient way to capture exceptions in interactive Python; returned values are captured by "_", -but exceptions currently are not. This could be spelled: +but exceptions currently are not. This could be spelled:: ->>> expr except Exception as e: e + >>> expr except Exception as e: e (The inner scope idea is tempting, but currently CPython handles list comprehensions with a nested function call, as this is considered @@ -668,11 +712,15 @@ breaking any existing code, as 'as' is already a keyword. One example where this could possibly be useful is Lib/imaplib.py:568:: - try: typ, dat = self._simple_command('LOGOUT') - except: typ, dat = 'NO', ['%s: %s' % sys.exc_info()[:2]] + + try: typ, dat = self._simple_command('LOGOUT') + except: typ, dat = 'NO', ['%s: %s' % sys.exc_info()[:2]] + This could become:: - typ, dat = (self._simple_command('LOGOUT') - except BaseException as e: ('NO', '%s: %s' % (type(e), e))) + + typ, dat = (self._simple_command('LOGOUT') + except BaseException as e: ('NO', '%s: %s' % (type(e), e))) + Or perhaps some other variation. This is hardly the most compelling use-case, but an intelligent look at this code could tidy it up significantly. In the absence of further examples showing any need of the exception object, I have @@ -701,7 +749,7 @@ ExpressionError in the current scope, with a built-in default such as (ValueError, UnicodeError, AttributeError, EOFError, IOError, OSError, LookupError, NameError, ZeroDivisionError). All of these were rejected, -for severa reasons. +for several reasons. * First and foremost, consistency with the statement form of try/except would be broken. Just as a list comprehension or ternary if expression @@ -754,6 +802,7 @@ This is more compelling when one or both of the deferred sub-proposals of multiple except clauses and/or exception capturing is included. In their absence, the parentheses would be thus:: + value = expr except ExceptionType: default value = expr (except ExceptionType: default) @@ -761,6 +810,7 @@ thinking the except clause is separate from the expression, or into thinking this is a function call, makes this non-compelling. The expression can, of course, be parenthesized if desired, as can the default:: + value = (expr) except ExceptionType: (default) @@ -778,9 +828,11 @@ pass For instance, a common use-case is attempting the removal of a file:: + os.unlink(some_file) except OSError: pass There is an equivalent already in Python 3.4, however, in contextlib:: + from contextlib import suppress with suppress(OSError): os.unlink(some_file) -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Feb 21 06:08:53 2014 From: python-checkins at python.org (yury.selivanov) Date: Fri, 21 Feb 2014 06:08:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_463=3A_Few_more_markup_fi?= =?utf-8?q?xes?= Message-ID: <3fVggT4FTYz7LjV@mail.python.org> http://hg.python.org/peps/rev/e412cc3a0a91 changeset: 5380:e412cc3a0a91 user: Yury Selivanov date: Fri Feb 21 00:08:48 2014 -0500 summary: PEP 463: Few more markup fixes HGe: Enter commit message. Lines beginning with 'HG:' are removed. files: pep-0463.txt | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pep-0463.txt b/pep-0463.txt --- a/pep-0463.txt +++ b/pep-0463.txt @@ -752,23 +752,23 @@ for several reasons. * First and foremost, consistency with the statement form of try/except -would be broken. Just as a list comprehension or ternary if expression -can be explained by "breaking it out" into its vertical statement form, -an expression-except should be able to be explained by a relatively -mechanical translation into a near-equivalent statement. Any form of -syntax common to both should therefore have the same semantics in each, -and above all should not have the subtle difference of catching more in -one than the other, as it will tend to attract unnoticed bugs. + would be broken. Just as a list comprehension or ternary if expression + can be explained by "breaking it out" into its vertical statement form, + an expression-except should be able to be explained by a relatively + mechanical translation into a near-equivalent statement. Any form of + syntax common to both should therefore have the same semantics in each, + and above all should not have the subtle difference of catching more in + one than the other, as it will tend to attract unnoticed bugs. * Secondly, the set of appropriate exceptions to catch would itself be -a huge point of contention. It would be impossible to predict exactly -which exceptions would "make sense" to be caught; why bless some of them -with convenient syntax and not others? + a huge point of contention. It would be impossible to predict exactly + which exceptions would "make sense" to be caught; why bless some of them + with convenient syntax and not others? * And finally (this partly because the recommendation was that a bare -except should be actively encouraged, once it was reduced to a "reasonable" -set of exceptions), any situation where you catch an exception you don't -expect to catch is an unnecessary bug magnet. + except should be actively encouraged, once it was reduced to a "reasonable" + set of exceptions), any situation where you catch an exception you don't + expect to catch is an unnecessary bug magnet. Consequently, the use of a bare 'except' is down to two possibilities: either it is syntactically forbidden in the expression form, or it is -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Feb 21 07:34:53 2014 From: python-checkins at python.org (yury.selivanov) Date: Fri, 21 Feb 2014 07:34:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=3A_Fix_getfullargs?= =?utf-8?q?pec_to_support_builtin_module-level_functions=2E_Issue?= Message-ID: <3fVjZj1Vxxz7LjP@mail.python.org> http://hg.python.org/cpython/rev/2000c27ebe80 changeset: 89314:2000c27ebe80 user: Yury Selivanov date: Fri Feb 21 01:32:42 2014 -0500 summary: inspect: Fix getfullargspec to support builtin module-level functions. Issue #20711 files: Lib/inspect.py | 11 +++++++++-- Lib/test/test_inspect.py | 7 +++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1827,9 +1827,16 @@ p(f.args.kwarg, empty) if self_parameter is not None: + # Possibly strip the bound argument: + # - We *always* strip first bound argument if + # it is a module. + # - We don't strip first bound argument if + # skip_bound_arg is False. assert parameters - if getattr(obj, '__self__', None) and skip_bound_arg: - # strip off self, it's already been bound + _self = getattr(obj, '__self__', None) + self_isbound = _self is not None + self_ismodule = ismodule(_self) + if self_isbound and (self_ismodule or skip_bound_arg): parameters.pop(0) else: # for builtins, self parameter is always positional-only! diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -643,6 +643,13 @@ self.assertFullArgSpecEquals(_pickle.Pickler(io.BytesIO()).dump, args_e=['self', 'obj'], formatted='(self, obj)') + self.assertFullArgSpecEquals( + os.stat, + args_e=['path'], + kwonlyargs_e=['dir_fd', 'follow_symlinks'], + kwonlydefaults_e={'dir_fd': None, 'follow_symlinks': True}, + formatted='(path, *, dir_fd=None, follow_symlinks=True)') + @cpython_only @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 21 08:35:01 2014 From: python-checkins at python.org (larry.hastings) Date: Fri, 21 Feb 2014 08:35:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320710=3A_The_pydo?= =?utf-8?q?c_summary_line_no_longer_displays_the_=22self=22_parameter?= Message-ID: <3fVkw573L8z7MkQ@mail.python.org> http://hg.python.org/cpython/rev/5e73bb72662e changeset: 89315:5e73bb72662e user: Larry Hastings date: Thu Feb 20 23:34:46 2014 -0800 summary: Issue #20710: The pydoc summary line no longer displays the "self" parameter for bound methods. Previous to this change, it displayed "self" for methods implemented in Python but not methods implemented in C; it is now both internally consistent and consistent with inspect.Signature. files: Lib/pydoc.py | 21 ++++++++++++--- Lib/test/test_pydoc.py | 40 ++++++++++++++++++++++++++--- Misc/NEWS | 3 ++ 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -137,6 +137,19 @@ inspect.isbuiltin(obj) or inspect.ismethoddescriptor(obj)) +def _is_bound_method(fn): + """ + Returns True if fn is a bound method, regardless of whether + fn was implemented in Python or in C. + """ + if inspect.ismethod(fn): + return True + if inspect.isbuiltin(fn): + self = getattr(fn, '__self__', None) + return not (inspect.ismodule(self) or (self is None)) + return False + + def allmethods(cl): methods = {} for key, value in inspect.getmembers(cl, _is_some_method): @@ -898,7 +911,7 @@ anchor = (cl and cl.__name__ or '') + '-' + name note = '' skipdocs = 0 - if inspect.ismethod(object): + if _is_bound_method(object): imclass = object.__self__.__class__ if cl: if imclass is not cl: @@ -909,7 +922,6 @@ object.__self__.__class__, mod) else: note = ' unbound %s method' % self.classlink(imclass,mod) - object = object.__func__ if name == realname: title = '%s' % (anchor, realname) @@ -924,7 +936,7 @@ title = '%s = %s' % ( anchor, name, reallink) argspec = None - if inspect.isfunction(object) or inspect.isbuiltin(object): + if inspect.isroutine(object): try: signature = inspect.signature(object) except (ValueError, TypeError): @@ -1304,7 +1316,7 @@ name = name or realname note = '' skipdocs = 0 - if inspect.ismethod(object): + if _is_bound_method(object): imclass = object.__self__.__class__ if cl: if imclass is not cl: @@ -1315,7 +1327,6 @@ object.__self__.__class__, mod) else: note = ' unbound %s method' % classname(imclass,mod) - object = object.__func__ if name == realname: title = self.bold(realname) diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -6,6 +6,7 @@ import inspect import pydoc import keyword +import _pickle import pkgutil import re import string @@ -699,12 +700,41 @@ self.assertIsNone(pydoc.locate(name)) self.assertRaises(ImportError, pydoc.render_doc, name) + @staticmethod + def _get_summary_line(o): + text = pydoc.plain(pydoc.render_doc(o)) + lines = text.split('\n') + assert len(lines) >= 2 + return lines[2] + + # these should include "self" + def test_unbound_python_method(self): + self.assertEqual(self._get_summary_line(textwrap.TextWrapper.wrap), + "wrap(self, text)") + @requires_docstrings - def test_builtin_signatures(self): - # test producing signatures from builtins - stat_sig = pydoc.render_doc(os.stat) - self.assertEqual(pydoc.plain(stat_sig).splitlines()[2], - 'stat(path, *, dir_fd=None, follow_symlinks=True)') + def test_unbound_builtin_method(self): + self.assertEqual(self._get_summary_line(_pickle.Pickler.dump), + "dump(self, obj, /)") + + # these no longer include "self" + def test_bound_python_method(self): + t = textwrap.TextWrapper() + self.assertEqual(self._get_summary_line(t.wrap), + "wrap(text) method of textwrap.TextWrapper instance") + + @requires_docstrings + def test_bound_builtin_method(self): + s = StringIO() + p = _pickle.Pickler(s) + self.assertEqual(self._get_summary_line(p.dump), + "dump(obj, /) method of _pickle.Pickler instance") + + # this should *never* include self! + @requires_docstrings + def test_module_level_callable(self): + self.assertEqual(self._get_summary_line(os.stat), + "stat(path, *, dir_fd=None, follow_symlinks=True)") @unittest.skipUnless(threading, 'Threading required for this test.') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,9 @@ Library ------- +- Issue #20710: The pydoc summary line no longer displays the "self" parameter + for bound methods. + - Issue #20654: Fixed pydoc for enums with zero value. Patch by Vajrasky Kok. - Issue #20635: Fixed grid_columnconfigure() and grid_rowconfigure() methods of -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 21 09:13:26 2014 From: python-checkins at python.org (larry.hastings) Date: Fri, 21 Feb 2014 09:13:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?release=3A_More_tweaking_of_my_threef?= =?utf-8?q?ourtool=2E?= Message-ID: <3fVlmQ6LmZz7MjF@mail.python.org> http://hg.python.org/release/rev/39f56476d896 changeset: 74:39f56476d896 user: Larry Hastings date: Fri Feb 21 00:13:24 2014 -0800 summary: More tweaking of my threefourtool. files: 3.4/threefourtool.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/3.4/threefourtool.py b/3.4/threefourtool.py --- a/3.4/threefourtool.py +++ b/3.4/threefourtool.py @@ -443,7 +443,11 @@ result = os.system(cmd) print() if result != 0: - print("Process return code:", result) + print("*" * 79) + print("*" * 79) + print("** Process return code:", result ) + print("*" * 79) + print("*" * 79) else: cmd() -- Repository URL: http://hg.python.org/release From python-checkins at python.org Fri Feb 21 09:28:11 2014 From: python-checkins at python.org (victor.stinner) Date: Fri, 21 Feb 2014 09:28:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2319748=3A_On_AIX?= =?utf-8?q?=2C_time=2Emktime=28=29_now_raises_an_OverflowError_for_year?= Message-ID: <3fVm5R3Yvnz7MjF@mail.python.org> http://hg.python.org/cpython/rev/502c8b7e8ad2 changeset: 89316:502c8b7e8ad2 user: Victor Stinner date: Fri Feb 21 09:27:17 2014 +0100 summary: Issue #19748: On AIX, time.mktime() now raises an OverflowError for year outsize range [1902; 2037]. files: Lib/test/test_time.py | 2 +- Misc/NEWS | 10 ++++++++++ Modules/timemodule.c | 11 +++++++++++ 3 files changed, 22 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -228,7 +228,7 @@ self.assertEqual(time.ctime(t), 'Sun Sep 16 01:03:52 1973') t = time.mktime((2000, 1, 1, 0, 0, 0, 0, 0, -1)) self.assertEqual(time.ctime(t), 'Sat Jan 1 00:00:00 2000') - for year in [-100, 100, 1000, 2000, 10000]: + for year in [-100, 100, 1000, 2000, 2050, 10000]: try: testval = time.mktime((year, 1, 10) + (0,)*6) except (ValueError, OverflowError): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,16 @@ Python News +++++++++++ +What's New in Python 3.4.1? +=========================== + +Library +------- + +- Issue #19748: On AIX, time.mktime() now raises an OverflowError for year + outsize range [1902; 2037]. + + What's New in Python 3.4.0 release candidate 2? =============================================== diff --git a/Modules/timemodule.c b/Modules/timemodule.c --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -823,7 +823,18 @@ time_t tt; if (!gettmarg(tup, &buf)) return NULL; +#ifdef _AIX + /* year < 1902 or year > 2037 */ + if (buf.tm_year < 2 || buf.tm_year > 137) { + /* Issue #19748: On AIX, mktime() doesn't report overflow error for + * timestamp < -2^31 or timestamp > 2**31-1. */ + PyErr_SetString(PyExc_OverflowError, + "mktime argument out of range"); + return NULL; + } +#else buf.tm_wday = -1; /* sentinel; original value ignored */ +#endif tt = mktime(&buf); /* Return value of -1 does not necessarily mean an error, but tm_wday * cannot remain set to -1 if mktime succeeded. */ -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Feb 21 09:37:55 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 21 Feb 2014 09:37:55 +0100 Subject: [Python-checkins] Daily reference leaks (d57df3f72715): sum=55 Message-ID: results for d57df3f72715 on branch "default" -------------------------------------------- test_multiprocessing_spawn leaked [0, 0, 38] references, sum=38 test_multiprocessing_spawn leaked [0, 0, 17] memory blocks, sum=17 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogLBT2Mh', '-x'] From python-checkins at python.org Fri Feb 21 11:09:06 2014 From: python-checkins at python.org (larry.hastings) Date: Fri, 21 Feb 2014 11:09:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?release=3A_Fix_dumb_bug_with_=22tar?= =?utf-8?q?=22_command=2E?= Message-ID: <3fVpKt5NGmz7LjV@mail.python.org> http://hg.python.org/release/rev/ec23a5570958 changeset: 75:ec23a5570958 user: Larry Hastings date: Fri Feb 21 02:09:06 2014 -0800 summary: Fix dumb bug with "tar" command. files: 3.4/threefourtool.py | 14 ++++++++++---- 1 files changed, 10 insertions(+), 4 deletions(-) diff --git a/3.4/threefourtool.py b/3.4/threefourtool.py --- a/3.4/threefourtool.py +++ b/3.4/threefourtool.py @@ -26,6 +26,10 @@ outgoing = "/home/larry/src/python/34outgoing" +def system(s): + print(s) + os.system(s) + def yes_no(): while True: s = input("Are you sure? (y/n) >") @@ -693,7 +697,8 @@ def tar(self): time = now() - tardir = "/home/larry/src/python/python-" + time + tarbase = "python_3.4.0rc2_" + time + tardir = "/home/larry/src/python/" + tarbase def remove_dir(dir): if os.path.isdir(dir): shutil.rmtree(dir) @@ -702,21 +707,22 @@ remove_dir(tardir) os.chdir("/home/larry/src/python") - os.system("hg clone 3.4 " + tardir) + system("hg clone 3.4 " + tardir) os.chdir(tardir) + system("hg update -r 3.4") remove_dir(".hg") for prefix in ('.hg', '.bzr', '.git'): for filename in glob.glob(prefix + '*'): os.unlink(filename) os.chdir("/home/larry/src/python") - os.system("tar cvfz " + outgoing + "/python.3.4.{}.tgz python-{}".format(time, time)) + system("tar cvfz " + outgoing + "/" + tarbase + ".tgz " + tarbase) remove_dir(tardir) def rsync(self): os.chdir(outgoing) - os.system("rsync -av * midwinter.com:public_html/3.4.status") + system("rsync -av * midwinter.com:public_html/3.4.status") def asyncio(self): -- Repository URL: http://hg.python.org/release From python-checkins at python.org Fri Feb 21 13:42:48 2014 From: python-checkins at python.org (donald.stufft) Date: Fri, 21 Feb 2014 13:42:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Upgrade_pip_from_1=2E5=2E3?= =?utf-8?b?IHRvIDEuNS40?= Message-ID: <3fVslD5ddSz7LjN@mail.python.org> http://hg.python.org/cpython/rev/005d0678f93c changeset: 89317:005d0678f93c user: Donald Stufft date: Fri Feb 21 07:42:39 2014 -0500 summary: Upgrade pip from 1.5.3 to 1.5.4 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/pip-1.5.3-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-1.5.4-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -10,7 +10,7 @@ _SETUPTOOLS_VERSION = "2.1" -_PIP_VERSION = "1.5.3" +_PIP_VERSION = "1.5.4" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-1.5.3-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-1.5.3-py2.py3-none-any.whl deleted file mode 100644 index 31cee0aea7ef59dc070f3a7845c09699e95a97e8..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-1.5.4-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-1.5.4-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e07d4767a0cc5d6367948bd18149602b2e050fd4 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 21 23:31:55 2014 From: python-checkins at python.org (richard.oudkerk) Date: Fri, 21 Feb 2014 23:31:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320114=3A_Double_t?= =?utf-8?q?imeout_in_test=5Fsemaphore=5Ftracker=28=29_to_reduce?= Message-ID: <3fW6pz0qrQz7N5n@mail.python.org> http://hg.python.org/cpython/rev/5057eaff9d68 changeset: 89318:5057eaff9d68 user: Richard Oudkerk date: Fri Feb 21 22:29:58 2014 +0000 summary: Issue #20114: Double timeout in test_semaphore_tracker() to reduce chance of sporadic failures. files: Lib/test/_test_multiprocessing.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3651,7 +3651,7 @@ _multiprocessing.sem_unlink(name1) p.terminate() p.wait() - time.sleep(1.0) + time.sleep(2.0) with self.assertRaises(OSError) as ctx: _multiprocessing.sem_unlink(name2) # docs say it should be ENOENT, but OSX seems to give EINVAL -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 21 23:55:00 2014 From: python-checkins at python.org (victor.stinner) Date: Fri, 21 Feb 2014 23:55:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2311188=2C_=2319748?= =?utf-8?q?=3A_mktime=28=29_returns_-1_on_error=2E_On_Linux=2C_the_tm=5Fwd?= =?utf-8?q?ay_field?= Message-ID: <3fW7Kc2crZz7N6Z@mail.python.org> http://hg.python.org/cpython/rev/00e94e454813 changeset: 89319:00e94e454813 user: Victor Stinner date: Fri Feb 21 23:54:32 2014 +0100 summary: Issue #11188, #19748: mktime() returns -1 on error. On Linux, the tm_wday field is used as a sentinel () to detect if -1 is really an error or a valid timestamp. On AIX, tm_wday is unchanged even on success and so cannot be used as a sentinel. files: Lib/test/test_time.py | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -346,6 +346,13 @@ def test_mktime(self): # Issue #1726687 for t in (-2, -1, 0, 1): + if sys.platform.startswith('aix') and t == -1: + # Issue #11188, #19748: mktime() returns -1 on error. On Linux, + # the tm_wday field is used as a sentinel () to detect if -1 is + # really an error or a valid timestamp. On AIX, tm_wday is + # unchanged even on success and so cannot be used as a + # sentinel. + continue try: tt = time.localtime(t) except (OverflowError, OSError): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 22 00:31:21 2014 From: python-checkins at python.org (yury.selivanov) Date: Sat, 22 Feb 2014 00:31:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_inspect=2Esignature=3A_Che?= =?utf-8?q?ck_for_function-like_objects_before_builtins=2E_Issue_=2317159?= Message-ID: <3fW87Y5ZD0z7N7B@mail.python.org> http://hg.python.org/cpython/rev/d6aa3fa646e2 changeset: 89320:d6aa3fa646e2 user: Yury Selivanov date: Fri Feb 21 18:30:53 2014 -0500 summary: inspect.signature: Check for function-like objects before builtins. Issue #17159 files: Lib/inspect.py | 8 ++++---- Lib/test/test_inspect.py | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1911,15 +1911,15 @@ return sig.replace(parameters=new_params) - if _signature_is_builtin(obj): - return _signature_from_builtin(Signature, obj, - skip_bound_arg=skip_bound_arg) - if isfunction(obj) or _signature_is_functionlike(obj): # If it's a pure Python function, or an object that is duck type # of a Python function (Cython functions, for instance), then: return Signature.from_function(obj) + if _signature_is_builtin(obj): + return _signature_from_builtin(Signature, obj, + skip_bound_arg=skip_bound_arg) + if isinstance(obj, functools.partial): wrapped_sig = _signature_internal(obj.func, follow_wrapper_chains, diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -14,6 +14,7 @@ import types import unicodedata import unittest +import unittest.mock try: from concurrent.futures import ThreadPoolExecutor @@ -1836,6 +1837,21 @@ ('kwargs', ..., ..., "var_keyword")), ...)) + # Test with cython-like builtins: + _orig_isdesc = inspect.ismethoddescriptor + def _isdesc(obj): + if hasattr(obj, '_builtinmock'): + return True + return _orig_isdesc(obj) + + with unittest.mock.patch('inspect.ismethoddescriptor', _isdesc): + builtin_func = funclike(func) + # Make sure that our mock setup is working + self.assertFalse(inspect.ismethoddescriptor(builtin_func)) + builtin_func._builtinmock = True + self.assertTrue(inspect.ismethoddescriptor(builtin_func)) + self.assertEqual(inspect.signature(builtin_func), sig_func) + def test_signature_functionlike_class(self): # We only want to duck type function-like objects, # not classes. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 22 05:27:56 2014 From: python-checkins at python.org (yury.selivanov) Date: Sat, 22 Feb 2014 05:27:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_463=3A_More_updates_by_Ch?= =?utf-8?q?ris_Angelico?= Message-ID: <3fWGjm4pcRz7N70@mail.python.org> http://hg.python.org/peps/rev/c52a2ae3d98e changeset: 5381:c52a2ae3d98e user: Yury Selivanov date: Fri Feb 21 23:27:51 2014 -0500 summary: PEP 463: More updates by Chris Angelico files: pep-0463.txt | 197 ++++++++++++++++---------------------- 1 files changed, 84 insertions(+), 113 deletions(-) diff --git a/pep-0463.txt b/pep-0463.txt --- a/pep-0463.txt +++ b/pep-0463.txt @@ -41,9 +41,6 @@ * min(sequence, default=default) - keyword argument in place of ValueError -* sum(sequence, start=default) - slightly different but can do the - same job - * statistics.mean(data) - no way to handle an empty iterator @@ -131,11 +128,11 @@ The proposal adds this:: lst = [1, 2] - value = lst[2] except IndexError: "No value" + value = (lst[2] except IndexError: "No value") Specifically, the syntax proposed is:: - expr except exception_list: default + (expr except exception_list: default) where expr, exception_list, and default are all expressions. First, expr is evaluated. If no exception is raised, its value is the value @@ -146,6 +143,12 @@ becoming the value of the expression. As with the statement form of try/except, non-matching exceptions will propagate upward. +Parentheses are required around the entire expression, unless they +would be completely redundant, according to the same rules as generator +expressions follow. This guarantees correct interpretation of nested +except-expressions, and allows for future expansion of the syntax - +see below on multiple except clauses. + Note that the current proposal does not allow the exception object to be captured. Where this is needed, the statement form must be used. (See below for discussion and elaboration on this.) @@ -206,20 +209,39 @@ this proposal in the interests of simplicity, but are preserved in the table above as an accurate record of suggestions. +The four forms most supported by this proposal are, in order:: -Open Issues -=========== + value = (expr except Exception: default) + value = (expr except Exception -> default) + value = (expr except Exception pass default) + value = (expr except Exception then default) -Parentheses around the entire expression ----------------------------------------- +All four maintain left-to-right evaluation order: first the base expression, +then the exception list, and lastly the default. This is important, as the +expressions are evaluated lazily. By comparison, several of the ad-hoc +alternatives listed above must (by the nature of functions) evaluate their +default values eagerly. The preferred form, using the colon, parallels +try/except by using "except exception_list:", and parallels lambda by having +"keyword name_list: subexpression". Using the arrow introduces a token many +programmers will not be familiar with, and which currently has no similar +meaning, but is otherwise quite readable. The English word "pass" has a +vaguely similar meaning (consider the common usage "pass by value/reference" +for function arguments), and "pass" is already a keyword, but as its meaning +is distinctly unrelated, this may cause confusion. Using "then" makes sense +in English, but this introduces a new keyword to the language - albeit one +not in common use, but a new keyword all the same. -Generator expressions require parentheses, unless they would be -strictly redundant. Ambiguities with except expressions could be -resolved in the same way, forcing nested except-in-except trees to be -correctly parenthesized and requiring that the outer expression be -clearly delineated. `Steven D'Aprano elaborates on the issue.`__ +Left to right evaluation order is extremely important to readability, as it +parallels the order most expressions are evaluated. Alternatives such as:: -__ https://mail.python.org/pipermail/python-ideas/2014-February/025647.html + value = (expr except default if Exception) + +break this, by first evaluating the two ends, and then coming to the middle; +while this may not seem terrible (as the exception list will usually be a +constant), it does add to the confusion when multiple clauses meet, either +with multiple except/if or with the existing if/else, or a combination. +Using the preferred order, subexpressions will always be evaluated from +left to right, no matter how the syntax is nested. Example usage @@ -236,7 +258,7 @@ Retrieve an argument, defaulting to None:: - cond = args[1] except IndexError: None + cond = (args[1] except IndexError: None) # Lib/pdb.py:803: try: @@ -246,7 +268,7 @@ Fetch information from the system if available:: - pwd = os.getcwd() except OSError: None + pwd = (os.getcwd() except OSError: None) # Lib/tkinter/filedialog.py:210: try: @@ -256,7 +278,7 @@ Attempt a translation, falling back on the original:: - e.widget = self._nametowidget(W) except KeyError: W + e.widget = (self._nametowidget(W) except KeyError: W) # Lib/tkinter/__init__.py:1222: try: @@ -267,7 +289,7 @@ Read from an iterator, continuing with blank lines once it's exhausted:: - line = readline() except StopIteration: '' + line = (readline() except StopIteration: '') # Lib/lib2to3/pgen2/tokenize.py:370: try: @@ -280,7 +302,7 @@ separate assignments into a single large dict initialization:: # sys.abiflags may not be defined on all platforms. - _CONFIG_VARS['abiflags'] = sys.abiflags except AttributeError: '' + _CONFIG_VARS['abiflags'] = (sys.abiflags except AttributeError: '') # Lib/sysconfig.py:529: try: @@ -292,7 +314,7 @@ Retrieve an indexed item, defaulting to None (similar to dict.get):: def getNamedItem(self, name): - return self._attrs[name] except KeyError: None + return (self._attrs[name] except KeyError: None) # Lib/xml/dom/minidom.py:573: def getNamedItem(self, name): @@ -303,8 +325,8 @@ Translate numbers to names, falling back on the numbers:: - g = grp.getgrnam(tarinfo.gname)[2] except KeyError: tarinfo.gid - u = pwd.getpwnam(tarinfo.uname)[2] except KeyError: tarinfo.uid + g = (grp.getgrnam(tarinfo.gname)[2] except KeyError: tarinfo.gid) + u = (pwd.getpwnam(tarinfo.uname)[2] except KeyError: tarinfo.uid) # Lib/tarfile.py:2198: try: @@ -319,7 +341,7 @@ Perform some lengthy calculations in EAFP mode, handling division by zero as a sort of sticky NaN:: - value = calculate(x) except ZeroDivisionError: float("nan") + value = (calculate(x) except ZeroDivisionError: float("nan")) try: value = calculate(x) @@ -328,38 +350,13 @@ Calculate the mean of a series of numbers, falling back on zero:: - value = statistics.mean(lst) except statistics.StatisticsError: 0 + value = (statistics.mean(lst) except statistics.StatisticsError: 0) try: value = statistics.mean(lst) except statistics.StatisticsError: value = 0 -Retrieving a message from either a cache or the internet, with auth -check:: - - logging.info("Message shown to user: %s",((cache[k] - except LookupError: - (backend.read(k) except OSError: 'Resource not available') - ) - if check_permission(k) else 'Access denied' - ) except BaseException: "This is like a bare except clause") - - try: - if check_permission(k): - try: - _ = cache[k] - except LookupError: - try: - _ = backend.read(k) - except OSError: - _ = 'Resource not available' - else: - _ = 'Access denied' - except BaseException: - _ = "This is like a bare except clause" - logging.info("Message shown to user: %s", _) - Looking up objects in a sparse list of overrides:: (overrides[x] or default except IndexError: default).ping() @@ -419,11 +416,19 @@ status.append('%s:%d' % self.addr except TypeError: repr(self.addr)) +In each case, the narrowed scope of the try/except ensures that an unexpected +exception (for instance, AttributeError if "append" were misspelled) does not +get caught by the same handler. This is sufficiently unlikely to be reason +to break the call out into a separate line (as per the five line example +above), but it is a small benefit gained as a side-effect of the conversion. + Comparisons with other languages ================================ -(With thanks to Andrew Barnert for compiling this section.) +(With thanks to Andrew Barnert for compiling this section. Note that the +examples given here do not reflect the current version of the proposal, +and need to be edited.) `Ruby's`__ "begin?rescue?rescue?else?ensure?end" is an expression (potentially with statements inside it). It has the equivalent of an "as" @@ -611,23 +616,18 @@ it would be with the statement form, and as its syntax is a point on which consensus has not been reached, the entire feature is deferred. -In order to ensure compatibility with future versions, ensure that any -consecutive except operators are parenthesized to guarantee the -interpretation you expect. - Multiple 'except' keywords can be used, and they will all catch exceptions raised in the original expression (only):: # Will catch any of the listed exceptions thrown by expr; # any exception thrown by a default expression will propagate. value = (expr - except Exception1 [as e]: default1 - except Exception2 [as e]: default2 - # ... except ExceptionN [as e]: defaultN + except Exception1: default1 + except Exception2: default2 + # ... except ExceptionN: defaultN ) -Using parentheses to force an alternative interpretation works as -expected:: +Currently, one of the following forms must be used:: # Will catch an Exception2 thrown by either expr or default1 value = ( @@ -639,69 +639,35 @@ (default1 except Exception2: default2) ) -This last form is confusing and should be discouraged by PEP 8, but it -is syntactically legal: you can put any sort of expression inside a -ternary-except; ternary-except is an expression; therefore you can put -a ternary-except inside a ternary-except. - -Open question: Where there are multiple except clauses, should they be -separated by commas? It may be easier for the parser, that way:: - - value = (expr - except Exception1 [as e]: default1, - except Exception2 [as e]: default2, - # ... except ExceptionN [as e]: defaultN, - ) - -with an optional comma after the last, as per tuple rules. Downside: -Omitting the comma would be syntactically valid, and would have almost -identical semantics, but would nest the entire preceding expression in -its exception catching rig - a matching exception raised in the -default clause would be caught by the subsequent except clause. As -this difference is so subtle, it runs the risk of being a major bug -magnet. - -As a mitigation of this risk, this form:: - - value = expr except Exception1: default1 except Exception2: default2 - -could be syntactically forbidden, and parentheses required if the -programmer actually wants that behaviour:: - - value = (expr except Exception1: default1) except Exception2: default2 - -This would prevent the accidental omission of a comma from changing -the expression's meaning. +Listing multiple exception clauses without parentheses is a syntax error +(see above), and so a future version of Python is free to add this feature +without breaking any existing code. Capturing the exception object ------------------------------ In a try/except block, the use of 'as' to capture the exception object -creates a local name binding, and implicitly deletes that binding in a -finally clause. As 'finally' is not a part of this proposal (see -below), this makes it tricky to describe; also, this use of 'as' gives -a way to create a name binding in an expression context. Should the -default clause have an inner scope in which the name exists, shadowing -anything of the same name elsewhere? Should it behave the same way the -statement try/except does, and unbind the name? Should it bind the -name and leave it bound? (Almost certainly not; this behaviour was -changed in Python 3 for good reason.) +creates a local name binding, and implicitly deletes that binding (to +avoid creating a reference loop) in a finally clause. In an expression +context, this makes little sense, and a proper sub-scope would be +required to safely capture the exception object - something akin to the +way a list comprehension is handled. However, CPython currently +implements a comprehension's subscope with a nested function call, which +has consequences in some contexts such as class definitions, and is +therefore unsuitable for this proposal. Should there be, in future, a +way to create a true subscope (which could simplify comprehensions, +except expressions, with blocks, and possibly more), then this proposal +could be revived; until then, its loss is not a great one, as the simple +exception handling that is well suited to the expression notation used +here is generally concerned only with the type of the exception, and not +its value - further analysis below. -Additionally, this syntax would allow a convenient way to capture +This syntax would, admittedly, allow a convenient way to capture exceptions in interactive Python; returned values are captured by "_", but exceptions currently are not. This could be spelled:: - >>> expr except Exception as e: e - -(The inner scope idea is tempting, but currently CPython handles list -comprehensions with a nested function call, as this is considered -easier. It may be of value to simplify both comprehensions and except -expressions, but that is a completely separate proposal to this PEP; -alternatively, it may be better to stick with what's known to -work. `Nick Coghlan elaborates.`__) - -__ https://mail.python.org/pipermail/python-ideas/2014-February/025702.html + >>> (expr except Exception as e: e) An examination of the Python standard library shows that, while the use of 'as' is fairly common (occurring in roughly one except clause in five), @@ -732,6 +698,7 @@ finally clause -------------- + The statement form try... finally or try... except... finally has no logical corresponding expression form. Therefore the finally keyword is not a part of this proposal, in any way. @@ -813,6 +780,10 @@ value = (expr) except ExceptionType: (default) +As the entire expression is now required to be in parentheses (which had not +been decided at the time when this was debated), there is less need to +delineate this section, and in many cases it would be redundant. + Short-hand for "except: pass" ----------------------------- -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Feb 22 07:33:00 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 22 Feb 2014 07:33:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_use_sphinx_fro?= =?utf-8?q?m_its_own_virtualenv_=28closes_=2320693=29?= Message-ID: <3fWKV45Czsz7N6T@mail.python.org> http://hg.python.org/cpython/rev/b514339e41ef changeset: 89321:b514339e41ef branch: 2.7 parent: 89292:0199bff14c5c user: Benjamin Peterson date: Sat Feb 22 01:32:50 2014 -0500 summary: use sphinx from its own virtualenv (closes #20693) files: Doc/tools/dailybuild.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/tools/dailybuild.py b/Doc/tools/dailybuild.py --- a/Doc/tools/dailybuild.py +++ b/Doc/tools/dailybuild.py @@ -29,6 +29,7 @@ BUILDROOT = '/home/gbrandl/docbuild' +SPHINXBUILD = os.path.join(BUILDROOT, 'sphinx-env/bin/sphinx-build') WWWROOT = '/data/ftp.python.org/pub/docs.python.org' BRANCHES = [ @@ -47,7 +48,7 @@ print 'Running make autobuild' maketarget = 'autobuild-' + ('html' if quick else ('dev' if isdev else 'stable')) - if os.WEXITSTATUS(os.system('cd Doc; make %s' % maketarget)) == 2: + if os.WEXITSTATUS(os.system('cd Doc; make SPHINXBUILD=%s %s' % (SPHINXBUILD, maketarget))) == 2: print '*' * 80 return print 'Copying HTML files to %s' % target -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 22 09:27:02 2014 From: python-checkins at python.org (larry.hastings) Date: Sat, 22 Feb 2014 09:27:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?release=3A_More_churn_for_my_3=2E4_to?= =?utf-8?b?b2wu?= Message-ID: <3fWN1f0BLJz7N5l@mail.python.org> http://hg.python.org/release/rev/a32c27681900 changeset: 76:a32c27681900 user: Larry Hastings date: Sat Feb 22 02:26:18 2014 -0600 summary: More churn for my 3.4 tool. files: 3.4/threefourtool.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/3.4/threefourtool.py b/3.4/threefourtool.py --- a/3.4/threefourtool.py +++ b/3.4/threefourtool.py @@ -124,7 +124,7 @@ current_directory = os.getcwd() try: os.chdir("/home/larry/src/python/3.4") - p = subprocess.Popen(["/usr/bin/hg", "log"], stdout=subprocess.PIPE) + p = subprocess.Popen(["/usr/bin/hg", "log", "-v"], stdout=subprocess.PIPE) # with open("/home/larry/src/python/logtxt", "rt", encoding="utf-8") as f: # output = f.read() -- Repository URL: http://hg.python.org/release From solipsis at pitrou.net Sat Feb 22 09:43:20 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 22 Feb 2014 09:43:20 +0100 Subject: [Python-checkins] Daily reference leaks (d6aa3fa646e2): sum=59 Message-ID: results for d6aa3fa646e2 on branch "default" -------------------------------------------- test_multiprocessing_forkserver leaked [38, 0, 0] references, sum=38 test_multiprocessing_forkserver leaked [17, 0, 0] memory blocks, sum=17 test_site leaked [0, 2, 0] references, sum=2 test_site leaked [0, 2, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog9dAVMc', '-x'] From python-checkins at python.org Sat Feb 22 20:29:09 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 22 Feb 2014 20:29:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_importlib_depr?= =?utf-8?q?ecations=2E?= Message-ID: <3fWfjd25hyz7LkP@mail.python.org> http://hg.python.org/cpython/rev/8f54f601fd75 changeset: 89322:8f54f601fd75 parent: 89320:d6aa3fa646e2 user: R David Murray date: Sat Feb 22 14:28:46 2014 -0500 summary: whatsnew: importlib deprecations. This addresses issue #20199, if I got it right. The deprecation and replacement lists are based on the importlib documentation. files: Doc/whatsnew/3.4.rst | 28 ++++++++++++++++++++++++---- 1 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1527,10 +1527,30 @@ :meth:`difflib.SequenceMatcher.isbpopular` were removed: use ``x in sm.bjunk`` and ``x in sm.bpopular``, where *sm* is a :class:`~difflib.SequenceMatcher` object. -* :func:`importlib.util.module_for_loader` is pending deprecation. Using - :func:`importlib.util.module_to_load` and - :meth:`importlib.abc.Loader.init_module_attrs` allows subclasses of a loader - to more easily customize module loading. +* As mentioned in :ref:`whatsnew-pep-451`, a number of :mod:`importilb` + methods and functions are deprecated: :meth:`importlib.find_loader` is + replaced by :func:`importlib.util.find_spec`; + :meth:`importlib.machinery.PathFinder.find_module` is replaced by + :meth:`importlib.machinery.PathFinder.find_spec`; + :meth:`importlib.abc.MetaPathFinder.find_module` is replaced by + :meth:`importlib.abc.MetaPathFinder.find_spec`; + :meth:`importlib.abc.PathEntryFinder.find_loader` and + :meth:`~importlib.abc.PathEntryFinder.find_module` are replaced by + :meth:`importlib.abc.PathEntryFinder.find_spec`; all of the ``xxxLoader`` ABC + ``load_module`` methods (:meth:`importlib.abc.Loader.load_module`, + :meth:`importlib.abc.InspectLoader.load_module`, + :meth:`importlib.abc.FileLoader.load_module`, + :meth:`importlib.abc.SourceLoader.load_module`) should no longer be + implemented, instead loaders should implement an + ``exec_module`` method + (:meth:`importlib.abc.Loader.exec_module`, + :meth:`importlib.abc.InspectLoader.exec_module` + :meth:`importlib.abc.SourceLoader.exec_module`) and let the import system + take care of the rest; and + :meth:`importlib.abc.Loader.module_repr`, + :meth:`importlib.util.module_for_loader`, :meth:`importlib.util.set_loader`, + and :meth:`importlib.util.set_package` are no longer needed because their + functions are now handled automatically by the import system. * The :mod:`imp` module is pending deprecation. To keep compatibility with Python 2/3 code bases, the module's removal is currently not scheduled. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 22 21:06:23 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 22 Feb 2014 21:06:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_frozen_package?= =?utf-8?q?_=5F=5Fpath=5F=5F=3B_and_min/max_versionadded=2E?= Message-ID: <3fWgXb5VrSz7Ljw@mail.python.org> http://hg.python.org/cpython/rev/0695e465affe changeset: 89323:0695e465affe user: R David Murray date: Sat Feb 22 15:05:08 2014 -0500 summary: whatsnew: frozen package __path__; and min/max versionadded. files: Doc/library/functions.rst | 6 ++++++ Doc/whatsnew/3.4.rst | 13 ++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -781,6 +781,9 @@ such as ``sorted(iterable, key=keyfunc, reverse=True)[0]`` and ``heapq.nlargest(1, iterable, key=keyfunc)``. + .. versionadded:: 3.4 + The *default* keyword-only argument. + .. _func-memoryview: .. function:: memoryview(obj) @@ -812,6 +815,9 @@ such as ``sorted(iterable, key=keyfunc)[0]`` and ``heapq.nsmallest(1, iterable, key=keyfunc)``. + .. versionadded:: 3.4 + The *default* keyword-only argument. + .. function:: next(iterator[, default]) Retrieve the next item from the *iterator* by calling its diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -346,9 +346,10 @@ * Unicode database updated to UCD version 6.3. -* :func:`min` and :func:`max` now accept a *default* argument that can be used - to specify the value they return if the iterable they are evaluating has no - elements. Contributed by Julian Berman in :issue:`18111`. +* :func:`min` and :func:`max` now accept a *default* keyword-only argument that + can be used to specify the value they return if the iterable they are + evaluating has no elements. (Contributed by Julian Berman in + :issue:`18111`.) * Module objects are now :mod:`weakref`'able. @@ -1805,6 +1806,12 @@ similarly to ``__kwdefaults__``. (Contributed by Yury Selivanov in :issue:`20625`). +* Frozen packages used to have their ``__path__`` set to the package name, + but this could cause the import system to do the wrong thing on submodule + imports if there was also a directory with the same name as the frozen + package. The ``__path__`` for frozen packages is now set to ``[]`` + (:issue:`18065`). + Changes in the C API -------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 22 22:02:44 2014 From: python-checkins at python.org (eric.snow) Date: Sat, 22 Feb 2014 22:02:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320484=3A_Disable_?= =?utf-8?q?the_2_remaining_=22modules=22_tests_in_test=5Fpydoc=2E?= Message-ID: <3fWhnc5qzKz7N76@mail.python.org> http://hg.python.org/cpython/rev/13edfab6c3c0 changeset: 89324:13edfab6c3c0 user: Eric Snow date: Sat Feb 22 13:57:08 2014 -0700 summary: Issue #20484: Disable the 2 remaining "modules" tests in test_pydoc. I'll look into re-enabling them in issue #20128. files: Lib/test/test_pydoc.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -618,6 +618,7 @@ self.assertEqual(out.getvalue(), '') self.assertEqual(err.getvalue(), '') + @unittest.skip('causes undesireable side-effects (#20128)') def test_modules(self): # See Helper.listmodules(). num_header_lines = 2 @@ -633,6 +634,7 @@ self.assertGreaterEqual(num_lines, expected) + @unittest.skip('causes undesireable side-effects (#20128)') def test_modules_search(self): # See Helper.listmodules(). expected = 'pydoc - ' @@ -645,7 +647,7 @@ self.assertIn(expected, result) - @unittest.skip('some buildbots are not cooperating (#20123)') + @unittest.skip('some buildbots are not cooperating (#20128)') def test_modules_search_builtin(self): expected = 'gc - ' -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 22 22:34:46 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 22 Feb 2014 22:34:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_Windows_uses_V?= =?utf-8?q?irtualAlloc=2C_--version_goes_to_stdout=2E?= Message-ID: <3fWjVZ0rL8z7LkL@mail.python.org> http://hg.python.org/cpython/rev/fc089cf0cf32 changeset: 89325:fc089cf0cf32 user: R David Murray date: Sat Feb 22 15:35:37 2014 -0500 summary: whatsnew: Windows uses VirtualAlloc, --version goes to stdout. files: Doc/whatsnew/3.4.rst | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1422,6 +1422,7 @@ (Contributed by Ysj Ray and Victor Stinner in :issue:`7330`.) +.. _other-improvements-3.4: Other Improvements ------------------ @@ -1510,6 +1511,10 @@ * :func:`html.escape` is now 10x faster. (Contributed by Matt Bryant in :issue:`18020`.) +* On Windows, the native ``VirtualAlloc`` is now used instead of the CRT + ``malloc`` in ``obmalloc``. Artificial benchmarks show about a 3% memory + savings. + Deprecated ========== @@ -1683,6 +1688,10 @@ CPython interpreter is now off by default. It can be re-enabled using the ``-X showrefcount`` option. (Contributed by Ezio Melotti in :issue:`17323`.) +* The python command and most stdlib scripts (as well as :mod:`argparse`) now + output ``--version`` information to ``stdout`` instead of ``stderr`` (for + issue list see :ref:`other-improvements-3.4` above). + Changes in the Python API ------------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 22 22:34:47 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 22 Feb 2014 22:34:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_PyStructSequen?= =?utf-8?q?ce=5FInitType2=2C_Victor=27s_MemoryError_fixes=2E?= Message-ID: <3fWjVb2Bcvz7LkL@mail.python.org> http://hg.python.org/cpython/rev/ff30ddaab7e8 changeset: 89326:ff30ddaab7e8 user: R David Murray date: Sat Feb 22 16:02:22 2014 -0500 summary: whatsnew: PyStructSequence_InitType2, Victor's MemoryError fixes. I'm documenting this new function, but I'm wondering if this will trigger someone to think about whether or not this actually makes sense :) files: Doc/c-api/tuple.rst | 8 ++++++++ Doc/whatsnew/3.4.rst | 8 ++++++++ 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Doc/c-api/tuple.rst b/Doc/c-api/tuple.rst --- a/Doc/c-api/tuple.rst +++ b/Doc/c-api/tuple.rst @@ -129,6 +129,14 @@ Initializes a struct sequence type *type* from *desc* in place. +.. c:function:: void PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) + + The same as ``PyStructSequence_InitType``, but returns ``0`` on success and ``-1`` on + failure. + + .. versionadded:: 3.4 + + .. c:type:: PyStructSequence_Desc Contains the meta information of a struct sequence type to create. diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1421,6 +1421,10 @@ specifications for ``%s``, ``%A``, ``%U``, ``%V``, ``%S``, and ``%R``. (Contributed by Ysj Ray and Victor Stinner in :issue:`7330`.) +* New function :c:func:`PyStructSequence_InitType2` supplements the + existing :c:func:`PyStructSequence_InitType` function. The difference + is that it returns ``0`` on success and ``-1`` on failure. + .. _other-improvements-3.4: @@ -1466,6 +1470,10 @@ uses of :ref:`__prepare__ `. (Contributed by Benjamin Peterson in :issue:`17853`.) +* A number of MemoryError-related crashes were identified and fixed by Victor + Stinner using his :pep:`445`-based ``pyfailmalloc`` tool (:issue:`18408`, + :issue:`18520`). + Significant Optimizations ------------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 22 22:34:48 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 22 Feb 2014 22:34:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_os=2Epath=2Eis?= =?utf-8?q?mount_recognizes_volumes_mounted_below_root=2E?= Message-ID: <3fWjVc3tGDz7N9J@mail.python.org> http://hg.python.org/cpython/rev/8fd64292175e changeset: 89327:8fd64292175e user: R David Murray date: Sat Feb 22 16:31:26 2014 -0500 summary: whatsnew: os.path.ismount recognizes volumes mounted below root. files: Doc/library/os.path.rst | 8 +++++++- Doc/whatsnew/3.4.rst | 3 +++ 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -194,10 +194,16 @@ .. function:: ismount(path) Return ``True`` if pathname *path* is a :dfn:`mount point`: a point in a file - system where a different file system has been mounted. The function checks + system where a different file system has been mounted. On POSIX, the function checks whether *path*'s parent, :file:`path/..`, is on a different device than *path*, or whether :file:`path/..` and *path* point to the same i-node on the same device --- this should detect mount points for all Unix and POSIX variants. + On Windows, a drive letter root and a share UNC are always mount + points, and for any other path ``GetVolumePathName`` is called to see if it + is different from the input path. + + .. versionadded:: 3.4 + Support for detecting non-root mount points on Windows. .. function:: join(path1[, path2[, ...]]) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -960,6 +960,9 @@ :func:`os.path.samefile` implementation is now shared between Unix and Windows). (Contributed by Brian Curtin in :issue:`11939`.) +:func:`os.path.ismount` now recognizes volumes mounted below a drive +root on Windows. (Contributed by Tim Golden in :issue:`9035`.) + pdb --- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 22 22:34:49 2014 From: python-checkins at python.org (r.david.murray) Date: Sat, 22 Feb 2014 22:34:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Reflow_paragraph=2E?= Message-ID: <3fWjVd5VmDz7N97@mail.python.org> http://hg.python.org/cpython/rev/9db97583d666 changeset: 89328:9db97583d666 user: R David Murray date: Sat Feb 22 16:32:07 2014 -0500 summary: Reflow paragraph. files: Doc/library/os.path.rst | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/library/os.path.rst b/Doc/library/os.path.rst --- a/Doc/library/os.path.rst +++ b/Doc/library/os.path.rst @@ -193,14 +193,14 @@ .. function:: ismount(path) - Return ``True`` if pathname *path* is a :dfn:`mount point`: a point in a file - system where a different file system has been mounted. On POSIX, the function checks - whether *path*'s parent, :file:`path/..`, is on a different device than *path*, - or whether :file:`path/..` and *path* point to the same i-node on the same - device --- this should detect mount points for all Unix and POSIX variants. - On Windows, a drive letter root and a share UNC are always mount - points, and for any other path ``GetVolumePathName`` is called to see if it - is different from the input path. + Return ``True`` if pathname *path* is a :dfn:`mount point`: a point in a + file system where a different file system has been mounted. On POSIX, the + function checks whether *path*'s parent, :file:`path/..`, is on a different + device than *path*, or whether :file:`path/..` and *path* point to the same + i-node on the same device --- this should detect mount points for all Unix + and POSIX variants. On Windows, a drive letter root and a share UNC are + always mount points, and for any other path ``GetVolumePathName`` is called + to see if it is different from the input path. .. versionadded:: 3.4 Support for detecting non-root mount points on Windows. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Feb 22 23:39:36 2014 From: python-checkins at python.org (brian.curtin) Date: Sat, 22 Feb 2014 23:39:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Remove_myself_from_Window?= =?utf-8?q?s_and_winreg_entries=2C_as_I_no_longer_actively_use?= Message-ID: <3fWkxN0VhJz7Lk9@mail.python.org> http://hg.python.org/devguide/rev/1da1057719f9 changeset: 670:1da1057719f9 user: Brian Curtin date: Sat Feb 22 16:39:33 2014 -0600 summary: Remove myself from Windows and winreg entries, as I no longer actively use Windows. files: experts.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/experts.rst b/experts.rst --- a/experts.rst +++ b/experts.rst @@ -247,7 +247,7 @@ wave weakref fdrake, pitrou webbrowser georg.brandl -winreg brian.curtin*, stutzbach +winreg stutzbach winsound effbot (inactive) wsgiref pje xdrlib @@ -290,7 +290,7 @@ NetBSD1 OS2/EMX aimacintyre Solaris/OpenIndiana jcea -Windows tim.golden, brian.curtin +Windows tim.golden JVM/Java frank.wierzbicki =================== =========== -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sat Feb 22 23:44:49 2014 From: python-checkins at python.org (martin.v.loewis) Date: Sat, 22 Feb 2014 23:44:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320641=3A_Run_cust?= =?utf-8?q?om_actions_with_the_NoImpersonate_flag_to_support_UAC=2E?= Message-ID: <3fWl3P05pbz7LkL@mail.python.org> http://hg.python.org/cpython/rev/7b80f57f904e changeset: 89329:7b80f57f904e user: Martin v. L?wis date: Sat Feb 22 23:44:20 2014 +0100 summary: Issue #20641: Run custom actions with the NoImpersonate flag to support UAC. files: Misc/NEWS | 3 +++ Tools/msi/msi.py | 20 +++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -116,6 +116,9 @@ Build ----- +- Issue #20641: Run MSI custom actions (pip installation, pyc compilation) + with the NoImpersonate flag, to support elevated execution (UAC). + - Issue #20221: Removed conflicting (or circular) hypot definition when compiled with VS 2010 or above. Initial patch by Tabrez Mohammed. diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py --- a/Tools/msi/msi.py +++ b/Tools/msi/msi.py @@ -435,12 +435,13 @@ ("SetLauncherDirToWindows", 307, "LAUNCHERDIR", "[WindowsFolder]"), # msidbCustomActionTypeExe + msidbCustomActionTypeSourceFile # See "Custom Action Type 18" - ("CompilePyc", 18, "python.exe", compileargs), - ("CompilePyo", 18, "python.exe", "-O "+compileargs), - ("CompileGrammar", 18, "python.exe", lib2to3args), # msidbCustomActionTypeInScript (1024); run during actual installation - ("UpdatePip", 18+1024, "python.exe", updatepipargs), - ("RemovePip", 18, "python.exe", removepipargs), + # msidbCustomActionTypeNoImpersonate (2048); run action in system account, not user account + ("CompilePyc", 18+1024+2048, "python.exe", compileargs), + ("CompilePyo", 18+1024+2048, "python.exe", "-O "+compileargs), + ("CompileGrammar", 18+1024+2048, "python.exe", lib2to3args), + ("UpdatePip", 18+1024+2048, "python.exe", updatepipargs), + ("RemovePip", 18+1024+2048, "python.exe", removepipargs), ]) # UI Sequences, see "InstallUISequence Table", "Using a Sequence Table" @@ -483,17 +484,14 @@ # remove pip when state changes to INSTALLSTATE_ABSENT # run before RemoveFiles ("RemovePip", "&pip_feature=2", 3499), - ("CompilePyc", "COMPILEALL", 6800), - ("CompilePyo", "COMPILEALL", 6801), - ("CompileGrammar", "COMPILEALL", 6802), + ("CompilePyc", "COMPILEALL", 4002), + ("CompilePyo", "COMPILEALL", 4003), + ("CompileGrammar", "COMPILEALL", 4004), ]) add_data(db, "AdminExecuteSequence", [("InitialTargetDir", 'TARGETDIR=""', 750), ("SetDLLDirToTarget", 'DLLDIR=""', 751), ("SetLauncherDirToTarget", 'LAUNCHERDIR=""', 752), - ("CompilePyc", "COMPILEALL", 6800), - ("CompilePyo", "COMPILEALL", 6801), - ("CompileGrammar", "COMPILEALL", 6802), ]) ##################################################################### -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 02:53:20 2014 From: python-checkins at python.org (ethan.furman) Date: Sun, 23 Feb 2014 02:53:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Incorporate_comments_from_las?= =?utf-8?q?t_round_of_emails_=28in_late_January=29?= Message-ID: <3fWqDw1j9Tz7LkL@mail.python.org> http://hg.python.org/peps/rev/e39f10322362 changeset: 5382:e39f10322362 user: Ethan Furman date: Sat Feb 22 17:53:31 2014 -0800 summary: Incorporate comments from last round of emails (in late January) files: pep-0461.txt | 114 ++++++++++++++++++++++++-------------- 1 files changed, 71 insertions(+), 43 deletions(-) diff --git a/pep-0461.txt b/pep-0461.txt --- a/pep-0461.txt +++ b/pep-0461.txt @@ -1,5 +1,5 @@ PEP: 461 -Title: Adding % formatting to bytes +Title: Adding % formatting to bytes and bytearray Version: $Revision$ Last-Modified: $Date$ Author: Ethan Furman @@ -8,7 +8,7 @@ Content-Type: text/x-rst Created: 2014-01-13 Python-Version: 3.5 -Post-History: 2014-01-14, 2014-01-15, 2014-01-17 +Post-History: 2014-01-14, 2014-01-15, 2014-01-17, 2014-02-22 Resolution: @@ -16,18 +16,40 @@ ======== This PEP proposes adding % formatting operations similar to Python 2's ``str`` -type to ``bytes`` [1]_ [2]_. +type to ``bytes`` and ``bytearray`` [1]_ [2]_. + + +Rationale +========= + +While interpolation is usually thought of as a string operation, there are +cases where interpolation on ``bytes`` or ``bytearrays`` make sense, and the +work needed to make up for this missing functionality detracts from the overall +readability of the code. + + +Motivation +========== + +With Python 3 and the split between ``str`` and ``bytes``, one small but +important area of programming became slightly more difficult, and much more +painful -- wire format protocols [3]_. + +This area of programming is characterized by a mixture of binary data and +ASCII compatible segments of text (aka ASCII-encoded text). Bringing back a +restricted %-interpolation for ``bytes`` and ``bytearray`` will aid both in +writing new wire format code, and in porting Python 2 wire format code. Overriding Principles ===================== -In order to avoid the problems of auto-conversion and Unicode exceptions that -could plague Py2 code, all object checking will be done by duck-typing, not by -values contained in a Unicode representation [3]_. +In order to avoid the problems of auto-conversion and Unicode exceptions +that could plague Python 2 code, :class:`str` objects will not be supported as +interpolation values [4]_ [5]_. -Proposed semantics for bytes formatting +Proposed semantics for ``bytes`` and ``bytearray`` formatting ======================================= %-interpolation @@ -59,15 +81,15 @@ >>> b'%c' % b'a' b'a' -``%s`` is restricted in what it will accept: +``%s`` is restricted in what it will accept:: -- input type supports ``Py_buffer`` [4]_? - use it to collect the necessary bytes + - input type supports ``Py_buffer`` [6]_? + use it to collect the necessary bytes -- input type is something else? - use its ``__bytes__`` method [5]_ ; if there isn't one, raise a ``TypeError`` + - input type is something else? + use its ``__bytes__`` method [7]_ ; if there isn't one, raise a ``TypeError`` -Examples:: +Examples: >>> b'%s' % b'abc' b'abc' @@ -75,7 +97,7 @@ >>> b'%s' % 3.14 Traceback (most recent call last): ... - TypeError: 3.14 has no __bytes__ method + TypeError: 3.14 has no __bytes__ method, use a numeric code instead >>> b'%s' % 'hello world!' Traceback (most recent call last): @@ -83,28 +105,24 @@ TypeError: 'hello world' has no __bytes__ method, perhaps you need to encode it? .. note:: + Because the ``str`` type does not have a ``__bytes__`` method, attempts to directly use ``'a string'`` as a bytes interpolation value will raise an - exception. To use ``'string'`` values, they must be encoded or otherwise - transformed into a ``bytes`` sequence:: + exception. To use strings they must be encoded or otherwise transformed + into a ``bytes`` sequence:: 'a string'.encode('latin-1') - -Numeric Format Codes --------------------- - -To properly handle ``int`` and ``float`` subclasses, ``int()``, ``index()``, -and ``float()`` will be called on the objects intended for (``d``, ``i``, -``u``), (``b``, ``o``, ``x``, ``X``), and (``e``, ``E``, ``f``, ``F``, ``g``, -``G``). +``%a`` will call :func:``ascii()`` on the interpolated value's :func:``repr()``. +This is intended as a debugging aid, rather than something that should be used +in production. Non-ascii values will be encoded to either ``\xnn`` or ``\unnnn`` +representation. Unsupported codes ----------------- -``%r`` (which calls ``__repr__``), and ``%a`` (which calls ``ascii()`` on -``__repr__``) are not supported. +``%r`` (which calls ``__repr__`` and returns a :class:`str`) is not supported. Proposed variations @@ -113,41 +131,51 @@ It was suggested to let ``%s`` accept numbers, but since numbers have their own format codes this idea was discarded. -It has been suggested to use ``%b`` for bytes instead of ``%s``. - -- Rejected as ``%b`` does not exist in Python 2.x %-interpolation, which is - why we are using ``%s``. - It has been proposed to automatically use ``.encode('ascii','strict')`` for ``str`` arguments to ``%s``. -- Rejected as this would lead to intermittent failures. Better to have the - operation always fail so the trouble-spot can be correctly fixed. + - Rejected as this would lead to intermittent failures. Better to have the + operation always fail so the trouble-spot can be correctly fixed. It has been proposed to have ``%s`` return the ascii-encoded repr when the value is a ``str`` (b'%s' % 'abc' --> b"'abc'"). -- Rejected as this would lead to hard to debug failures far from the problem - site. Better to have the operation always fail so the trouble-spot can be - easily fixed. + - Rejected as this would lead to hard to debug failures far from the problem + site. Better to have the operation always fail so the trouble-spot can be + easily fixed. -Originally this PEP also proposed adding format style formatting, but it -was decided that format and its related machinery were all strictly text -(aka ``str``) based, and it was dropped. +Originally this PEP also proposed adding format-style formatting, but it was +decided that format and its related machinery were all strictly text (aka +``str``) based, and it was dropped. Various new special methods were proposed, such as ``__ascii__``, ``__format_bytes__``, etc.; such methods are not needed at this time, but can be visited again later if real-world use shows deficiencies with this solution. +Open Questions +============== + +It has been suggested to use ``%b`` for bytes as well as ``%s``. + + - Pro: clearly says 'this is bytes'; should be used for new code. + + - Con: does not exist in Python 2.x, so we would have two ways of doing the + same thing, ``%s`` and ``%b``, with no difference between them. + + + Footnotes ========= .. [1] http://docs.python.org/2/library/stdtypes.html#string-formatting -.. [2] neither string.Template, format, nor str.format are under consideration. -.. [3] %c is not an exception as neither of its possible arguments are unicode. -.. [4] http://docs.python.org/3/c-api/buffer.html -.. [5] http://docs.python.org/3/reference/datamodel.html#object.__bytes__ +.. [2] neither string.Template, format, nor str.format are under consideration +.. [3] https://mail.python.org/pipermail/python-dev/2014-January/131518.html +.. [4] to use a str object in a bytes interpolation, encode it first +.. [5] %c is not an exception as neither of its possible arguments are str +.. [6] http://docs.python.org/3/c-api/buffer.html + examples: ``memoryview``, ``array.array``, ``bytearray``, ``bytes`` +.. [7] http://docs.python.org/3/reference/datamodel.html#object.__bytes__ Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Feb 23 03:40:59 2014 From: python-checkins at python.org (ethan.furman) Date: Sun, 23 Feb 2014 03:40:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_added_Objections_section=3B_f?= =?utf-8?q?ixed_formatting?= Message-ID: <3fWrHv6TFGz7Lkh@mail.python.org> http://hg.python.org/peps/rev/fddeb948a6a3 changeset: 5383:fddeb948a6a3 user: Ethan Furman date: Sat Feb 22 18:41:14 2014 -0800 summary: added Objections section; fixed formatting files: pep-0461.txt | 33 ++++++++++++++++++++++++++++----- 1 files changed, 28 insertions(+), 5 deletions(-) diff --git a/pep-0461.txt b/pep-0461.txt --- a/pep-0461.txt +++ b/pep-0461.txt @@ -45,7 +45,7 @@ ===================== In order to avoid the problems of auto-conversion and Unicode exceptions -that could plague Python 2 code, :class:`str` objects will not be supported as +that could plague Python 2 code, ``str`` objects will not be supported as interpolation values [4]_ [5]_. @@ -73,7 +73,7 @@ ``%c`` will insert a single byte, either from an ``int`` in range(256), or from a ``bytes`` argument of length 1, not from a ``str``. -Example: +Example:: >>> b'%c' % 48 b'0' @@ -89,7 +89,7 @@ - input type is something else? use its ``__bytes__`` method [7]_ ; if there isn't one, raise a ``TypeError`` -Examples: +Examples:: >>> b'%s' % b'abc' b'abc' @@ -113,7 +113,7 @@ 'a string'.encode('latin-1') -``%a`` will call :func:``ascii()`` on the interpolated value's :func:``repr()``. +``%a`` will call ``ascii()`` on the interpolated value's ``repr()``. This is intended as a debugging aid, rather than something that should be used in production. Non-ascii values will be encoded to either ``\xnn`` or ``\unnnn`` representation. @@ -122,7 +122,7 @@ Unsupported codes ----------------- -``%r`` (which calls ``__repr__`` and returns a :class:`str`) is not supported. +``%r`` (which calls ``__repr__`` and returns a '`str`') is not supported. Proposed variations @@ -153,6 +153,27 @@ be visited again later if real-world use shows deficiencies with this solution. +Objections +========== + +The objections raised against this PEP were mainly variations on two themes:: + + - the ``bytes`` and ``bytearray`` types are for pure binary data, with no + assumptions about encodings + - offering %-interpolation that assumes an ASCII encoding will be an + attractive nuisance and lead us back to the problems of the Python 2 + ``str``/``unicode`` text model + +As was seen during the discussion, ``bytes`` and ``bytearray`` are also used +for mixed binary data and ASCII-compatible segments: file formats such as +``dbf`` and ``pdf``, network protocols such as ``ftp`` and ``email``, etc. + +``bytes`` and ``bytearray`` already have several methods which assume an ASCII +compatible encoding. ``upper()``, ``isalpha()``, and ``expandtabs()`` to name +just a few. %-interpolation, with its very restricted mini-language, will not +be any more of a nuisance than the already existing methdods. + + Open Questions ============== @@ -176,6 +197,8 @@ .. [6] http://docs.python.org/3/c-api/buffer.html examples: ``memoryview``, ``array.array``, ``bytearray``, ``bytes`` .. [7] http://docs.python.org/3/reference/datamodel.html#object.__bytes__ +.. [8] mainly implicit encode/decode, with intermittent errors when the data + was not ASCII compatible Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Feb 23 06:38:41 2014 From: python-checkins at python.org (terry.reedy) Date: Sun, 23 Feb 2014 06:38:41 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNzMw?= =?utf-8?q?=3A_Fix_typo_reported_by_Claudiu_Popa=2E?= Message-ID: <3fWwDx5FQ6z7Lk9@mail.python.org> http://hg.python.org/cpython/rev/5c366a5e4284 changeset: 89330:5c366a5e4284 branch: 3.3 parent: 89309:9aedb876c2d7 user: Terry Jan Reedy date: Sun Feb 23 00:37:16 2014 -0500 summary: Issue #20730: Fix typo reported by Claudiu Popa. files: Lib/idlelib/GrepDialog.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/GrepDialog.py b/Lib/idlelib/GrepDialog.py --- a/Lib/idlelib/GrepDialog.py +++ b/Lib/idlelib/GrepDialog.py @@ -98,7 +98,7 @@ def findfiles(self, dir, base, rec): try: names = os.listdir(dir or os.curdir) - except OSerror as msg: + except OSError as msg: print(msg) return [] list = [] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 06:38:42 2014 From: python-checkins at python.org (terry.reedy) Date: Sun, 23 Feb 2014 06:38:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3fWwDy6zDHz7LkP@mail.python.org> http://hg.python.org/cpython/rev/659fff320e1e changeset: 89331:659fff320e1e parent: 89329:7b80f57f904e parent: 89330:5c366a5e4284 user: Terry Jan Reedy date: Sun Feb 23 00:37:46 2014 -0500 summary: Merge with 3.3 files: Lib/idlelib/GrepDialog.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/GrepDialog.py b/Lib/idlelib/GrepDialog.py --- a/Lib/idlelib/GrepDialog.py +++ b/Lib/idlelib/GrepDialog.py @@ -98,7 +98,7 @@ def findfiles(self, dir, base, rec): try: names = os.listdir(dir or os.curdir) - except OSerror as msg: + except OSError as msg: print(msg) return [] list = [] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 06:43:00 2014 From: python-checkins at python.org (guido.van.rossum) Date: Sun, 23 Feb 2014 06:43:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Typos_=28stdandard=29=2E?= Message-ID: <3fWwKw0lm1z7LjT@mail.python.org> http://hg.python.org/peps/rev/4ce536918cbd changeset: 5384:4ce536918cbd user: Guido van Rossum date: Sat Feb 22 21:42:54 2014 -0800 summary: Typos (stdandard). files: pep-3156.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-3156.txt b/pep-3156.txt --- a/pep-3156.txt +++ b/pep-3156.txt @@ -315,7 +315,7 @@ The default implementation uses ``time.monotonic()``. Books could be written about the implications of this choice. Better read the docs -for the stdandard library ``time`` module. +for the standard library ``time`` module. Embedded Event Loops -------------------- @@ -878,7 +878,7 @@ (the default) or ``subprocess.STDOUT``. By default a new pipe will be created and connected. When ``subprocess.STDOUT`` is specified, the subprocess's standard error stream will be connected to the same - pipe as the stdandard output stream. + pipe as the standard output stream. - ``bufsize``: The buffer size to be used when creating a pipe; this is passed to ``subprocess.Popen()``. In the default implementation -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Feb 23 08:27:40 2014 From: python-checkins at python.org (georg.brandl) Date: Sun, 23 Feb 2014 08:27:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Update_pydoc_t?= =?utf-8?q?opics=2E?= Message-ID: <3fWyfh1LRvz7Ljb@mail.python.org> http://hg.python.org/cpython/rev/a69945e43ff3 changeset: 89332:a69945e43ff3 branch: 3.3 parent: 89330:5c366a5e4284 user: Georg Brandl date: Sun Feb 23 08:24:37 2014 +0100 summary: Update pydoc topics. files: Lib/pydoc_data/topics.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Sat Jan 25 09:13:25 2014 +# Autogenerated by Sphinx on Sun Feb 23 08:13:25 2014 topics = {'assert': '\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': '\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the object\n allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nWARNING: Although the definition of assignment implies that overlaps\nbetween the left-hand side and the right-hand side are \'safe\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables are not safe! For instance, the\nfollowing program prints "[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions for the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': '\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', @@ -76,4 +76,4 @@ 'unary': '\nUnary arithmetic and bitwise operations\n***************************************\n\nAll unary arithmetic and bitwise operations have the same priority:\n\n u_expr ::= power | "-" u_expr | "+" u_expr | "~" u_expr\n\nThe unary "-" (minus) operator yields the negation of its numeric\nargument.\n\nThe unary "+" (plus) operator yields its numeric argument unchanged.\n\nThe unary "~" (invert) operator yields the bitwise inversion of its\ninteger argument. The bitwise inversion of "x" is defined as\n"-(x+1)". It only applies to integral numbers.\n\nIn all three cases, if the argument does not have the proper type, a\n"TypeError" exception is raised.\n', 'while': '\nThe "while" statement\n*********************\n\nThe "while" statement is used for repeated execution as long as an\nexpression is true:\n\n while_stmt ::= "while" expression ":" suite\n ["else" ":" suite]\n\nThis repeatedly tests the expression and, if it is true, executes the\nfirst suite; if the expression is false (which may be the first time\nit is tested) the suite of the "else" clause, if present, is executed\nand the loop terminates.\n\nA "break" statement executed in the first suite terminates the loop\nwithout executing the "else" clause\'s suite. A "continue" statement\nexecuted in the first suite skips the rest of the suite and goes back\nto testing the expression.\n', 'with': '\nThe "with" statement\n********************\n\nThe "with" statement is used to wrap the execution of a block with\nmethods defined by a context manager (see section *With Statement\nContext Managers*). This allows common "try"..."except"..."finally"\nusage patterns to be encapsulated for convenient reuse.\n\n with_stmt ::= "with" with_item ("," with_item)* ":" suite\n with_item ::= expression ["as" target]\n\nThe execution of the "with" statement with one "item" proceeds as\nfollows:\n\n1. The context expression (the expression given in the "with_item")\n is evaluated to obtain a context manager.\n\n2. The context manager\'s "__exit__()" is loaded for later use.\n\n3. The context manager\'s "__enter__()" method is invoked.\n\n4. If a target was included in the "with" statement, the return\n value from "__enter__()" is assigned to it.\n\n Note: The "with" statement guarantees that if the "__enter__()"\n method returns without an error, then "__exit__()" will always be\n called. Thus, if an error occurs during the assignment to the\n target list, it will be treated the same as an error occurring\n within the suite would be. See step 6 below.\n\n5. The suite is executed.\n\n6. The context manager\'s "__exit__()" method is invoked. If an\n exception caused the suite to be exited, its type, value, and\n traceback are passed as arguments to "__exit__()". Otherwise, three\n "None" arguments are supplied.\n\n If the suite was exited due to an exception, and the return value\n from the "__exit__()" method was false, the exception is reraised.\n If the return value was true, the exception is suppressed, and\n execution continues with the statement following the "with"\n statement.\n\n If the suite was exited for any reason other than an exception, the\n return value from "__exit__()" is ignored, and execution proceeds\n at the normal location for the kind of exit that was taken.\n\nWith more than one item, the context managers are processed as if\nmultiple "with" statements were nested:\n\n with A() as a, B() as b:\n suite\n\nis equivalent to\n\n with A() as a:\n with B() as b:\n suite\n\nChanged in version 3.1: Support for multiple context expressions.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n', - 'yield': '\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nThe "yield" statement is only used when defining a generator function,\nand is only used in the body of the generator function. Using a\n"yield" statement in a function definition is sufficient to cause that\ndefinition to create a generator function instead of a normal\nfunction.\n\nWhen a generator function is called, it returns an iterator known as a\ngenerator iterator, or more commonly, a generator. The body of the\ngenerator function is executed by calling the "next()" function on the\ngenerator repeatedly until it raises an exception.\n\nWhen a "yield" statement is executed, the state of the generator is\nfrozen and the value of "expression_list" is returned to "next()"\'s\ncaller. By "frozen" we mean that all local state is retained,\nincluding the current bindings of local variables, the instruction\npointer, and the internal evaluation stack: enough information is\nsaved so that the next time "next()" is invoked, the function can\nproceed exactly as if the "yield" statement were just another external\ncall.\n\nThe "yield" statement is allowed in the "try" clause of a "try" ...\n"finally" construct. If the generator is not resumed before it is\nfinalized (by reaching a zero reference count or by being garbage\ncollected), the generator-iterator\'s "close()" method will be called,\nallowing any pending "finally" clauses to execute.\n\nWhen "yield from " is used, it treats the supplied expression as\na subiterator, producing values from it until the underlying iterator\nis exhausted.\n\n Changed in version 3.3: Added "yield from " to delegate\n control flow to a subiterator\n\nFor full details of "yield" semantics, refer to the *Yield\nexpressions* section.\n\nSee also: **PEP 0255** - Simple Generators\n\n The proposal for adding generators and the "yield" statement to\n Python.\n\n **PEP 0342** - Coroutines via Enhanced Generators\n The proposal to enhance the API and syntax of generators, making\n them usable as simple coroutines.\n\n **PEP 0380** - Syntax for Delegating to a Subgenerator\n The proposal to introduce the "yield_from" syntax, making\n delegation to sub-generators easy.\n'} + 'yield': '\nThe "yield" statement\n*********************\n\n yield_stmt ::= yield_expression\n\nA "yield" statement is semantically equivalent to a *yield\nexpression*. The yield statement can be used to omit the parentheses\nthat would otherwise be required in the equivalent yield expression\nstatement. For example, the yield statements\n\n yield \n yield from \n\nare equivalent to the yield expression statements\n\n (yield )\n (yield from )\n\nYield expressions and statements are only used when defining a\n*generator* function, and are only used in the body of the generator\nfunction. Using yield in a function definition is sufficient to cause\nthat definition to create a generator function instead of a normal\nfunction.\n\nFor full details of "yield" semantics, refer to the *Yield\nexpressions* section.\n'} -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 08:34:25 2014 From: python-checkins at python.org (georg.brandl) Date: Sun, 23 Feb 2014 08:34:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTcx?= =?utf-8?q?=3A_skip_test=5Freadline=28=29_of_test=5Fcodecs_for_Windows_cod?= =?utf-8?q?e_page_65001=2E?= Message-ID: <3fWypT6hMNz7LjT@mail.python.org> http://hg.python.org/cpython/rev/d8f48717b74e changeset: 89333:d8f48717b74e branch: 3.3 user: Victor Stinner date: Sun Feb 09 13:11:53 2014 +0100 summary: Issue #20571: skip test_readline() of test_codecs for Windows code page 65001. The decoder does not support partial decoding yet for this code page. files: Lib/test/test_codecs.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -845,6 +845,9 @@ "\U00010fff\uD800") self.assertTrue(codecs.lookup_error("surrogatepass")) + def test_readline(self): + self.skipTest("issue #20571: code page 65001 codec does not " + "support partial decoder yet") class UTF7Test(ReadTest, unittest.TestCase): -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sun Feb 23 09:58:21 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 23 Feb 2014 09:58:21 +0100 Subject: [Python-checkins] Daily reference leaks (7b80f57f904e): sum=0 Message-ID: results for 7b80f57f904e on branch "default" -------------------------------------------- test_site leaked [0, 2, -2] references, sum=0 test_site leaked [0, 2, -2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog2wzVvq', '-x'] From python-checkins at python.org Sun Feb 23 16:13:44 2014 From: python-checkins at python.org (ezio.melotti) Date: Sun, 23 Feb 2014 16:13:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2320677=3A_fix_typo_in_en?= =?utf-8?q?um_docs=2E__Patch_by_Saimadhav_Heblikar=2E?= Message-ID: <3fX90S06fbz7LjS@mail.python.org> http://hg.python.org/cpython/rev/569589d3abb5 changeset: 89334:569589d3abb5 parent: 89331:659fff320e1e user: Ezio Melotti date: Sun Feb 23 17:13:31 2014 +0200 summary: #20677: fix typo in enum docs. Patch by Saimadhav Heblikar. files: Doc/library/enum.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -139,7 +139,7 @@ >>> Color['green'] -If have an enum member and need its :attr:`name` or :attr:`value`:: +If you have an enum member and need its :attr:`name` or :attr:`value`:: >>> member = Color.red >>> member.name -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 16:51:17 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 23 Feb 2014 16:51:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320637=3A_Key-shar?= =?utf-8?q?ing_now_also_works_for_instance_dictionaries_of?= Message-ID: <3fX9qn4JKWz7N6S@mail.python.org> http://hg.python.org/cpython/rev/16229573e73e changeset: 89335:16229573e73e user: Antoine Pitrou date: Sun Feb 23 16:50:07 2014 +0100 summary: Issue #20637: Key-sharing now also works for instance dictionaries of subclasses. Patch by Peter Ingebretson. files: Lib/test/test_types.py | 26 ++++++++++++++++++++++++-- Misc/ACKS | 1 + Misc/NEWS | 6 ++++++ Objects/typeobject.c | 3 +++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -1,6 +1,6 @@ # Python test set -- part 6, built-in types -from test.support import run_unittest, run_with_locale +from test.support import run_unittest, run_with_locale, cpython_only import collections import pickle import locale @@ -1170,9 +1170,31 @@ self.assertEqual(ns, ns_roundtrip, pname) +class SharedKeyTests(unittest.TestCase): + + @cpython_only + def test_subclasses(self): + # Verify that subclasses can share keys (per PEP 412) + class A: + pass + class B(A): + pass + + a, b = A(), B() + self.assertEqual(sys.getsizeof(vars(a)), sys.getsizeof(vars(b))) + self.assertLess(sys.getsizeof(vars(a)), sys.getsizeof({})) + a.x, a.y, a.z, a.w = range(4) + self.assertNotEqual(sys.getsizeof(vars(a)), sys.getsizeof(vars(b))) + a2 = A() + self.assertEqual(sys.getsizeof(vars(a)), sys.getsizeof(vars(a2))) + self.assertLess(sys.getsizeof(vars(a)), sys.getsizeof({})) + b.u, b.v, b.w, b.t = range(4) + self.assertLess(sys.getsizeof(vars(b)), sys.getsizeof({})) + + def test_main(): run_unittest(TypesTests, MappingProxyTests, ClassCreationTests, - SimpleNamespaceTests) + SimpleNamespaceTests, SharedKeyTests) if __name__ == '__main__': test_main() diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -585,6 +585,7 @@ Lars Immisch Bobby Impollonia Meador Inge +Peter Ingebretson Tony Ingraldi John Interrante Bob Ippolito diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,6 +5,12 @@ What's New in Python 3.4.1? =========================== +Core and Builtins +----------------- + +- Issue #20637: Key-sharing now also works for instance dictionaries of + subclasses. Patch by Peter Ingebretson. + Library ------- diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2472,6 +2472,9 @@ type->tp_dictoffset = slotoffset; slotoffset += sizeof(PyObject *); } + else if (!type->tp_dictoffset) { + type->tp_dictoffset = base->tp_dictoffset; + } if (type->tp_dictoffset) { et->ht_cached_keys = _PyDict_NewKeysForClass(); } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 17:42:10 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 23 Feb 2014 17:42:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_ExtensionFileL?= =?utf-8?q?oader=2Eget=5Ffilename=2E?= Message-ID: <3fXByV2tZFz7Mj3@mail.python.org> http://hg.python.org/cpython/rev/4d9c683ccda0 changeset: 89336:4d9c683ccda0 user: R David Murray date: Sun Feb 23 09:41:27 2014 -0500 summary: whatsnew: ExtensionFileLoader.get_filename. Also reflow mmap paragraph. files: Doc/whatsnew/3.4.rst | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -828,6 +828,11 @@ that decodes source from bytes using universal newline processing. This is useful for implementing :meth:`.InspectLoader.get_source` methods. +:class:`importlib.machinery.ExtensionFileLoader` now has a +:meth:`~importlib.machinery.ExtensionFileLoader.get_filename` method. This was +inadvertently omitted in the original implementation. (Contributed by Eric +Snow in :issue:`19152`.) + inspect ------- @@ -895,8 +900,8 @@ mmap ---- -mmap objects can now be weakref'ed. -(Contributed by Valerie Lambert in :issue:`4885`.) +mmap objects can now be weakref'ed. (Contributed by Valerie Lambert in +:issue:`4885`.) mock -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 17:42:11 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 23 Feb 2014 17:42:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_textwrap=2Esho?= =?utf-8?q?rten=2E?= Message-ID: <3fXByW4Fszz7Mj3@mail.python.org> http://hg.python.org/cpython/rev/4d615ab37804 changeset: 89337:4d615ab37804 user: R David Murray date: Sun Feb 23 10:22:07 2014 -0500 summary: whatsnew: textwrap.shorten. Also add the missing TextWrapper.shorten method doc. files: Doc/library/textwrap.rst | 10 ++++++++++ Doc/whatsnew/3.4.rst | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 0 deletions(-) diff --git a/Doc/library/textwrap.rst b/Doc/library/textwrap.rst --- a/Doc/library/textwrap.rst +++ b/Doc/library/textwrap.rst @@ -282,3 +282,13 @@ Wraps the single paragraph in *text*, and returns a single string containing the wrapped paragraph. + + + .. method:: shorten(text, width=70, *, placeholder=" [...]") + + Collapse and truncate the given text to fit in the given width. + The text first has its whitespace collapsed. If it then fits in + the *width*, it is returned unchanged. Otherwise, as many words + as possible are joined and then the *placeholder* is appended. + + .. versionadded:: 3.4 diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1210,6 +1210,20 @@ in :issue:`13390`.) +textwrap +-------- + +:mod:`textwrap` has a new function :func:`~textwrap.shorten`, implemented via a +new :class:`~textwrap.TextWrapper` method +:meth:`~textwrap.TextWrapper.shorten`, that provides a convenient way to create +a string that displays just the leading porting of an input string. It +collapses any whitespace, truncates the result to a specified width, and a +specified placeholder is added (by default, ``[...]``, stored in the new +:attr:`~textwrap.TextWrapper.placeholder` attribute of the +:class:`~textwrap.TextWrapper` object)). (Contributed by Antoine Pitrou in +:issue:`18585`.) + + traceback --------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 17:42:12 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 23 Feb 2014 17:42:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_hashlib=2Ehash?= =?utf-8?q?=2Ename_is_now_public_and_returns_lowercase_always=2E?= Message-ID: <3fXByX5Zjwz7N6C@mail.python.org> http://hg.python.org/cpython/rev/87dab1bf09c5 changeset: 89338:87dab1bf09c5 user: R David Murray date: Sun Feb 23 10:42:47 2014 -0500 summary: whatsnew: hashlib.hash.name is now public and returns lowercase always. files: Doc/whatsnew/3.4.rst | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -748,8 +748,15 @@ hashlib ------- -New :func:`hashlib.pbkdf2_hmac` function. -(Contributed by Christian Heimes in :issue:`18582`) +New :func:`hashlib.pbkdf2_hmac` function. (Contributed by Christian Heimes in +:issue:`18582`) + +The :attr:`~hashlib.hash.name` attribute of :mod:`hashlib` hash objects is now +a formally supported interface. It has always existed in CPython's +:mod:`hashlib` (although it did not return lower case names for all supported +hashes), but it was not a public interface and so some other Python +implementations have not previously supported it. (Contributed by Jason R. +Coombs in :issue:`18532`.) hmac @@ -1851,6 +1858,10 @@ package. The ``__path__`` for frozen packages is now set to ``[]`` (:issue:`18065`). +* :attr:`hashlib.hash.name` now always returns the identifier in lower case. + Previously some builtin hashes had uppercase names, but now that it is a + formal public interface the naming has been made consistent (:issue:`18532`). + Changes in the C API -------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 17:42:14 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 23 Feb 2014 17:42:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_devnull_fileno?= =?utf-8?q?/close/closed=2E?= Message-ID: <3fXByZ07GJz7N66@mail.python.org> http://hg.python.org/cpython/rev/54b73ec4efb8 changeset: 89339:54b73ec4efb8 user: R David Murray date: Sun Feb 23 11:21:59 2014 -0500 summary: whatsnew: devnull fileno/close/closed. files: Doc/whatsnew/3.4.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1081,6 +1081,11 @@ method will be called automatically at the end of the block. (Contributed by Serhiy Storchaka in :issue:`16488`.) +:class:`~select.devpoll` objects now have :meth:`~select.devpoll.fileno` and +:meth:`~select.devpoll.close` methods, as well as a new attribute +:attr:`~select.devpoll.closed`. (Contributed by Victor Stinner in +:issue:`18794`.) + shelve ------ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 17:42:15 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 23 Feb 2014 17:42:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_wording_in_news_entry?= =?utf-8?q?=2E?= Message-ID: <3fXByb1vlKz7N6F@mail.python.org> http://hg.python.org/cpython/rev/c7b5e7b78290 changeset: 89340:c7b5e7b78290 user: R David Murray date: Sun Feb 23 11:22:08 2014 -0500 summary: Fix wording in news entry. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1944,7 +1944,7 @@ - Issue #18394: Close cgi.FieldStorage's optional file. -- Issue #17702: On error, os.environb now removes suppress the except context +- Issue #17702: On error, os.environb now suppresses the exception context when raising a new KeyError with the original key. - Issue #16809: Fixed some tkinter incompabilities with Tcl/Tk 8.6. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 17:42:16 2014 From: python-checkins at python.org (r.david.murray) Date: Sun, 23 Feb 2014 17:42:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_pyvenv_--copie?= =?utf-8?q?s_option=2E?= Message-ID: <3fXByc3XS1z7N5Z@mail.python.org> http://hg.python.org/cpython/rev/fe8d416618e9 changeset: 89341:fe8d416618e9 user: R David Murray date: Sun Feb 23 11:36:25 2014 -0500 summary: whatsnew: pyvenv --copies option. Also added the missing documentation for new new option. files: Doc/using/venv-create.inc | 5 ++++- Doc/whatsnew/3.4.rst | 4 ++++ 2 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Doc/using/venv-create.inc b/Doc/using/venv-create.inc --- a/Doc/using/venv-create.inc +++ b/Doc/using/venv-create.inc @@ -38,6 +38,8 @@ virtual environment. --symlinks Try to use symlinks rather than copies, when symlinks are not the default for the platform. + --copies Try to use copies rather than symlinks, even when + symlinks are the default for the platform. --clear Delete the environment directory if it already exists. If not specified and the directory exists, an error is raised. @@ -47,7 +49,8 @@ environment (pip is bootstrapped by default) .. versionchanged:: 3.4 - Installs pip by default, added the ``--without-pip`` option + Installs pip by default, added the ``--without-pip`` and ``--copies`` + options If the target directory already exists an error will be raised, unless the ``--clear`` or ``--upgrade`` option was provided. diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1508,6 +1508,10 @@ Stinner using his :pep:`445`-based ``pyfailmalloc`` tool (:issue:`18408`, :issue:`18520`). +* The :ref:`pyvenv ` command now accepts a ``--copies`` option + to use copies rather than symlinks even on systems where symlinks are the + default. (Contributed by Vinay Sajip in :issue:`18807`.) + Significant Optimizations ------------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 18:57:02 2014 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 23 Feb 2014 18:57:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_add_post_history?= Message-ID: <3fXDct5Wrsz7Ljk@mail.python.org> http://hg.python.org/peps/rev/bd00c0d7b43b changeset: 5385:bd00c0d7b43b user: Benjamin Peterson date: Sun Feb 23 12:56:58 2014 -0500 summary: add post history files: pep-0387.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0387.txt b/pep-0387.txt --- a/pep-0387.txt +++ b/pep-0387.txt @@ -7,6 +7,7 @@ Type: Process Content-Type: text/x-rst Created: 18-Jun-2009 +Post-History: 19-Jun-2009 Abstract -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Feb 23 19:41:59 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 23 Feb 2014 19:41:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNzQz?= =?utf-8?q?=3A_Fix_a_reference_leak_in_test=5Ftcl=2E?= Message-ID: <3fXFcl4kClz7Lk5@mail.python.org> http://hg.python.org/cpython/rev/38a06e411698 changeset: 89342:38a06e411698 branch: 3.3 parent: 89333:d8f48717b74e user: Antoine Pitrou date: Sun Feb 23 19:39:06 2014 +0100 summary: Issue #20743: Fix a reference leak in test_tcl. files: Lib/test/test_tcl.py | 1 + Misc/NEWS | 2 ++ 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -376,6 +376,7 @@ result = arg return arg self.interp.createcommand('testfunc', testfunc) + self.addCleanup(self.interp.tk.deletecommand, 'testfunc') def check(value, expected, eq=self.assertEqual): r = self.interp.call('testfunc', value) self.assertIsInstance(result, str) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -117,6 +117,8 @@ Tests ----- +- Issue #20743: Fix a reference leak in test_tcl. + - Issue #20510: Rewrote test_exit in test_sys to match existing comments, use modern unittest features, and use helpers from test.script_helper instead of using subprocess directly. Patch by Gareth Rees. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 19:42:00 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 23 Feb 2014 19:42:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320743=3A_Fix_a_reference_leak_in_test=5Ftcl=2E?= Message-ID: <3fXFcm6DcPz7N61@mail.python.org> http://hg.python.org/cpython/rev/10b1f60a72fa changeset: 89343:10b1f60a72fa parent: 89341:fe8d416618e9 parent: 89342:38a06e411698 user: Antoine Pitrou date: Sun Feb 23 19:41:51 2014 +0100 summary: Issue #20743: Fix a reference leak in test_tcl. files: Lib/test/test_tcl.py | 1 + Misc/NEWS | 5 +++++ 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -376,6 +376,7 @@ result = arg return arg self.interp.createcommand('testfunc', testfunc) + self.addCleanup(self.interp.tk.deletecommand, 'testfunc') def check(value, expected, eq=self.assertEqual): r = self.interp.call('testfunc', value) self.assertIsInstance(result, str) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,11 @@ - Issue #19748: On AIX, time.mktime() now raises an OverflowError for year outsize range [1902; 2037]. +Tests +----- + +- Issue #20743: Fix a reference leak in test_tcl. + What's New in Python 3.4.0 release candidate 2? =============================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Feb 23 19:46:31 2014 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 23 Feb 2014 19:46:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNzQz?= =?utf-8?q?=3A_Fix_a_reference_leak_in_test=5Ftcl=2E?= Message-ID: <3fXFjz3Ht5z7Lk5@mail.python.org> http://hg.python.org/cpython/rev/00393de6919d changeset: 89344:00393de6919d branch: 2.7 parent: 89321:b514339e41ef user: Antoine Pitrou date: Sun Feb 23 19:39:06 2014 +0100 summary: Issue #20743: Fix a reference leak in test_tcl. files: Lib/test/test_tcl.py | 1 + Misc/NEWS | 2 ++ 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -386,6 +386,7 @@ result.append(arg) return arg self.interp.createcommand('testfunc', testfunc) + self.addCleanup(self.interp.tk.deletecommand, 'testfunc') def check(value, expected, expected2=None, eq=self.assertEqual): if expected2 is None: expected2 = expected diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -249,6 +249,8 @@ Tests ----- +- Issue #20743: Fix a reference leak in test_tcl. + - Issue #20510: Rewrote test_exit in test_sys to match existing comments, use modern unittest features, and use helpers from test.script_helper instead of using subprocess directly. Initial patch by Gareth Rees. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 00:01:29 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 24 Feb 2014 00:01:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNzUw?= =?utf-8?q?=2C_Enable_roundtrip_tests_for_new_5-tuple_untokenize=2E_The?= Message-ID: <3fXMN95Kn8z7N77@mail.python.org> http://hg.python.org/cpython/rev/8d6dd02a973f changeset: 89345:8d6dd02a973f branch: 3.3 parent: 89342:38a06e411698 user: Terry Jan Reedy date: Sun Feb 23 18:00:31 2014 -0500 summary: Issue #20750, Enable roundtrip tests for new 5-tuple untokenize. The constructed examples and all but 7 of the test/test_*.py files (run with -ucpu) pass. Remove those that fail the new test from the selection list. Patch partly based on patches by G. Brandl (#8478) and G. Rees (#12691). files: Lib/test/test_tokenize.py | 52 +++++++++++++++++++------- 1 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -578,9 +578,15 @@ >>> tempdir = os.path.dirname(f) or os.curdir >>> testfiles = glob.glob(os.path.join(tempdir, "test*.py")) -tokenize is broken on test_pep3131.py because regular expressions are broken on -the obscure unicode identifiers in it. *sigh* +Tokenize is broken on test_pep3131.py because regular expressions are +broken on the obscure unicode identifiers in it. *sigh* +With roundtrip extended to test the 5-tuple mode of untokenize, +7 more testfiles fail. Remove them also until the failure is diagnosed. + >>> testfiles.remove(os.path.join(tempdir, "test_pep3131.py")) + >>> for f in ('buffer', 'builtin', 'fileio', 'inspect', 'os', 'platform', 'sys'): + ... testfiles.remove(os.path.join(tempdir, "test_%s.py") % f) + ... >>> if not support.is_resource_enabled("cpu"): ... testfiles = random.sample(testfiles, 10) ... @@ -659,21 +665,39 @@ def roundtrip(f): """ Test roundtrip for `untokenize`. `f` is an open file or a string. - The source code in f is tokenized, converted back to source code via - tokenize.untokenize(), and tokenized again from the latter. The test - fails if the second tokenization doesn't match the first. + The source code in f is tokenized to both 5- and 2-tuples. + Both sequences are converted back to source code via + tokenize.untokenize(), and the latter tokenized again to 2-tuples. + The test fails if the 3 pair tokenizations do not match. + + When untokenize bugs are fixed, untokenize with 5-tuples should + reproduce code that does not contain a backslash continuation + following spaces. A proper test should test this. + + This function would be more useful for correcting bugs if it reported + the first point of failure, like assertEqual, rather than just + returning False -- or if it were only used in unittests and not + doctest and actually used assertEqual. """ + # Get source code and original tokenizations if isinstance(f, str): - f = BytesIO(f.encode('utf-8')) - try: - token_list = list(tokenize(f.readline)) - finally: + code = f.encode('utf-8') + else: + code = f.read() f.close() - tokens1 = [tok[:2] for tok in token_list] - new_bytes = untokenize(tokens1) - readline = (line for line in new_bytes.splitlines(keepends=True)).__next__ - tokens2 = [tok[:2] for tok in tokenize(readline)] - return tokens1 == tokens2 + readline = iter(code.splitlines(keepends=True)).__next__ + tokens5 = list(tokenize(readline)) + tokens2 = [tok[:2] for tok in tokens5] + # Reproduce tokens2 from pairs + bytes_from2 = untokenize(tokens2) + readline2 = iter(bytes_from2.splitlines(keepends=True)).__next__ + tokens2_from2 = [tok[:2] for tok in tokenize(readline2)] + # Reproduce tokens2 from 5-tuples + bytes_from5 = untokenize(tokens5) + readline5 = iter(bytes_from5.splitlines(keepends=True)).__next__ + tokens2_from5 = [tok[:2] for tok in tokenize(readline5)] + # Compare 3 versions + return tokens2 == tokens2_from2 == tokens2_from5 # This is an example from the docs, set up as a doctest. def decistmt(s): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 00:01:30 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 24 Feb 2014 00:01:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3=2C_=2320750?= Message-ID: <3fXMNB6nDlz7N7g@mail.python.org> http://hg.python.org/cpython/rev/73aa6d672b81 changeset: 89346:73aa6d672b81 parent: 89343:10b1f60a72fa parent: 89345:8d6dd02a973f user: Terry Jan Reedy date: Sun Feb 23 18:01:08 2014 -0500 summary: Merge with 3.3, #20750 files: Lib/test/test_tokenize.py | 52 +++++++++++++++++++------- 1 files changed, 38 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -578,9 +578,15 @@ >>> tempdir = os.path.dirname(f) or os.curdir >>> testfiles = glob.glob(os.path.join(tempdir, "test*.py")) -tokenize is broken on test_pep3131.py because regular expressions are broken on -the obscure unicode identifiers in it. *sigh* +Tokenize is broken on test_pep3131.py because regular expressions are +broken on the obscure unicode identifiers in it. *sigh* +With roundtrip extended to test the 5-tuple mode of untokenize, +7 more testfiles fail. Remove them also until the failure is diagnosed. + >>> testfiles.remove(os.path.join(tempdir, "test_pep3131.py")) + >>> for f in ('buffer', 'builtin', 'fileio', 'inspect', 'os', 'platform', 'sys'): + ... testfiles.remove(os.path.join(tempdir, "test_%s.py") % f) + ... >>> if not support.is_resource_enabled("cpu"): ... testfiles = random.sample(testfiles, 10) ... @@ -659,21 +665,39 @@ def roundtrip(f): """ Test roundtrip for `untokenize`. `f` is an open file or a string. - The source code in f is tokenized, converted back to source code via - tokenize.untokenize(), and tokenized again from the latter. The test - fails if the second tokenization doesn't match the first. + The source code in f is tokenized to both 5- and 2-tuples. + Both sequences are converted back to source code via + tokenize.untokenize(), and the latter tokenized again to 2-tuples. + The test fails if the 3 pair tokenizations do not match. + + When untokenize bugs are fixed, untokenize with 5-tuples should + reproduce code that does not contain a backslash continuation + following spaces. A proper test should test this. + + This function would be more useful for correcting bugs if it reported + the first point of failure, like assertEqual, rather than just + returning False -- or if it were only used in unittests and not + doctest and actually used assertEqual. """ + # Get source code and original tokenizations if isinstance(f, str): - f = BytesIO(f.encode('utf-8')) - try: - token_list = list(tokenize(f.readline)) - finally: + code = f.encode('utf-8') + else: + code = f.read() f.close() - tokens1 = [tok[:2] for tok in token_list] - new_bytes = untokenize(tokens1) - readline = (line for line in new_bytes.splitlines(keepends=True)).__next__ - tokens2 = [tok[:2] for tok in tokenize(readline)] - return tokens1 == tokens2 + readline = iter(code.splitlines(keepends=True)).__next__ + tokens5 = list(tokenize(readline)) + tokens2 = [tok[:2] for tok in tokens5] + # Reproduce tokens2 from pairs + bytes_from2 = untokenize(tokens2) + readline2 = iter(bytes_from2.splitlines(keepends=True)).__next__ + tokens2_from2 = [tok[:2] for tok in tokenize(readline2)] + # Reproduce tokens2 from 5-tuples + bytes_from5 = untokenize(tokens5) + readline5 = iter(bytes_from5.splitlines(keepends=True)).__next__ + tokens2_from5 = [tok[:2] for tok in tokenize(readline5)] + # Compare 3 versions + return tokens2 == tokens2_from2 == tokens2_from5 # This is an example from the docs, set up as a doctest. def decistmt(s): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 00:41:20 2014 From: python-checkins at python.org (antoine.pitrou) Date: Mon, 24 Feb 2014 00:41:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Restore_title_?= =?utf-8?q?style?= Message-ID: <3fXNG872sLz7Lk5@mail.python.org> http://hg.python.org/cpython/rev/a9464e900705 changeset: 89347:a9464e900705 branch: 2.7 parent: 89344:00393de6919d user: Antoine Pitrou date: Mon Feb 24 00:41:14 2014 +0100 summary: Restore title style files: Misc/NEWS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,3 +1,4 @@ ++++++++++++ Python News +++++++++++ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 03:38:12 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 03:38:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_unittest_drops?= =?utf-8?q?_references_to_successful_tests=2E?= Message-ID: <3fXSBD450Yz7MZt@mail.python.org> http://hg.python.org/cpython/rev/1063e7b57a88 changeset: 89348:1063e7b57a88 parent: 89346:73aa6d672b81 user: R David Murray date: Sun Feb 23 20:53:50 2014 -0500 summary: whatsnew: unittest drops references to successful tests. files: Doc/whatsnew/3.4.rst | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1286,6 +1286,14 @@ consistent test ordering. (Contributed by Martin Melin and Jeff Ramnani in :issue:`16709`.) +:class:`~unittest.TestSuite` now drops references to tests as soon as the test +has been run, if the test is successful. On Python interpreters that do +garbage collection, this allows the tests to be garbage collected if nothing +else is holding a reference to the test. It is possible to override this +behavior by creating a :class:`~unittest.TestSuite` subclass that defines a +custom ``_removeTestAtIndex`` method. (Contributed by Tom Wardill, Matt +McClure, and Andrew Svetlov in :issue:`11798`.) + venv ---- @@ -1871,6 +1879,16 @@ Previously some builtin hashes had uppercase names, but now that it is a formal public interface the naming has been made consistent (:issue:`18532`). +* Because :mod:`unittest.TestSuite` now drops references to tests after they + are run, test harnesses that re-use a :class:`~unittest.TestSuite` to re-run + a set of tests may fail. Test suites should not be re-used in this fashion + since it means state is retained between test runs, breaking the test + isolation that :mod:`unittest` is designed to provide. However, if the lack + of isolation is considered acceptable, the old behavior can be restored by + creating a :mod:`~unittest.TestSuite` subclass that defines a + ``_removeTestAtIndex`` method that does nothing (see + :meth:`.TestSuite.__iter__`) (:issue:`11798`). + Changes in the C API -------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 03:38:13 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 03:38:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_unittest_uses_?= =?utf-8?q?argparse_now=2E?= Message-ID: <3fXSBF6141z7MZt@mail.python.org> http://hg.python.org/cpython/rev/925528b20416 changeset: 89349:925528b20416 user: R David Murray date: Sun Feb 23 21:02:53 2014 -0500 summary: whatsnew: unittest uses argparse now. files: Doc/whatsnew/3.4.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1889,6 +1889,11 @@ ``_removeTestAtIndex`` method that does nothing (see :meth:`.TestSuite.__iter__`) (:issue:`11798`). +* :mod:`unittest` now uses :mod:`argparse` for command line parsing. There are + certain invalid command forms that used to work that are no longer allowed; + in theory this should not cause backward compatibility issues since the + disallowed command forms didn't make any sense and are unlikely to be in use. + Changes in the C API -------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 03:38:15 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 03:38:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_threading=2Ema?= =?utf-8?q?in=5Fthread=2C_os=2Eurandom_persistent_handle=2C_sunau=2Eopen_w?= =?utf-8?q?ith=2E?= Message-ID: <3fXSBH0fqwz7N65@mail.python.org> http://hg.python.org/cpython/rev/961ef3e15318 changeset: 89350:961ef3e15318 user: R David Murray date: Sun Feb 23 21:31:53 2014 -0500 summary: whatsnew: threading.main_thread, os.urandom persistent handle, sunau.open with. files: Doc/whatsnew/3.4.rst | 18 +++++++++++++++++- 1 files changed, 17 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1208,7 +1208,10 @@ The :meth:`~sunau.getparams` method now returns a namedtuple rather than a plain tuple. (Contributed by Claudiu Popa in :issue:`18901`.) -:meth:`sunau.open` now supports the context manager protocol (:issue:`18878`). +:meth:`sunau.open` now supports the context manager protocol: when used in a +:keyword:`with` block, the ``close`` method of the returned object will be +called automatically at the end of the block. (Contributed by Serhiy Storchaka +in :issue:`18878`.) sys @@ -1236,6 +1239,15 @@ :issue:`18585`.) +threading +--------- + +The :class:`~threading.Thread` object representing the main thread can be +obtained from the new :func:`~threading.main_thread` function. In normal +conditions this will be the thread from which the Python interpreter was +started. (Contributed by Andrew Svetlov in :issue:`18882`.) + + traceback --------- @@ -1569,6 +1581,10 @@ ``malloc`` in ``obmalloc``. Artificial benchmarks show about a 3% memory savings. +* :func:`os.urandom` now uses a lazily-opened persistent file descriptor + so as to avoid using many file descriptors when run in parallel from + multiple threads. (Contributed by Antoine Pitrou in :issue:`18756`.) + Deprecated ========== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 03:38:16 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 03:38:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_wording_in_NEWS_entry?= =?utf-8?q?=2E?= Message-ID: <3fXSBJ2ZFpz7N8f@mail.python.org> http://hg.python.org/cpython/rev/b34b34d3c5ad changeset: 89351:b34b34d3c5ad user: R David Murray date: Sun Feb 23 21:32:17 2014 -0500 summary: Fix wording in NEWS entry. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1902,7 +1902,7 @@ - Issue #18672: Fixed format specifiers for Py_ssize_t in debugging output in the _sre module. -- Issue #18830: inspect.getclasstree() no more produces duplicated entries even +- Issue #18830: inspect.getclasstree() no longer produces duplicate entries even when input list contains duplicates. - Issue #18878: sunau.open now supports the context manager protocol. Based on -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 05:40:42 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 24 Feb 2014 05:40:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzk5NzQ6?= =?utf-8?q?_When_untokenizing=2C_use_row_info_to_insert_backslash+newline?= =?utf-8?q?=2E?= Message-ID: <3fXVvZ3rhCz7MjV@mail.python.org> http://hg.python.org/cpython/rev/0f0e9b7d4f1d changeset: 89352:0f0e9b7d4f1d branch: 2.7 parent: 89347:a9464e900705 user: Terry Jan Reedy date: Sun Feb 23 23:32:59 2014 -0500 summary: Issue #9974: When untokenizing, use row info to insert backslash+newline. Original patches by A. Kuchling and G. Rees (#12691). files: Lib/test/test_tokenize.py | 16 +++++++++++++++- Lib/tokenize.py | 6 ++++++ 2 files changed, 21 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -4,7 +4,7 @@ >>> import glob, random, sys The tests can be really simple. Given a small fragment of source -code, print out a table with tokens. The ENDMARK is omitted for +code, print out a table with tokens. The ENDMARKER is omitted for brevity. >>> dump_tokens("1 + 1") @@ -618,6 +618,7 @@ class UntokenizeTest(TestCase): def test_bad_input_order(self): + # raise if previous row u = Untokenizer() u.prev_row = 2 u.prev_col = 2 @@ -625,8 +626,21 @@ u.add_whitespace((1,3)) self.assertEqual(cm.exception.args[0], 'start (1,3) precedes previous end (2,2)') + # raise if previous column in row self.assertRaises(ValueError, u.add_whitespace, (2,1)) + def test_backslash_continuation(self): + # The problem is that \ leaves no token + u = Untokenizer() + u.prev_row = 1 + u.prev_col = 1 + u.tokens = [] + u.add_whitespace((2, 0)) + self.assertEqual(u.tokens, ['\\\n']) + u.prev_row = 2 + u.add_whitespace((4, 4)) + self.assertEqual(u.tokens, ['\\\n', '\\\n\\\n', ' ']) + def test_iter_compat(self): u = Untokenizer() token = (NAME, 'Hello') diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -188,6 +188,10 @@ if row < self.prev_row or row == self.prev_row and col < self.prev_col: raise ValueError("start ({},{}) precedes previous end ({},{})" .format(row, col, self.prev_row, self.prev_col)) + row_offset = row - self.prev_row + if row_offset: + self.tokens.append("\\\n" * row_offset) + self.prev_col = 0 col_offset = col - self.prev_col if col_offset: self.tokens.append(" " * col_offset) @@ -199,6 +203,8 @@ self.compat(t, it) break tok_type, token, start, end, line = t + if tok_type == ENDMARKER: + break self.add_whitespace(start) self.tokens.append(token) self.prev_row, self.prev_col = end -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 05:40:43 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 24 Feb 2014 05:40:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzk5NzQ6?= =?utf-8?q?_When_untokenizing=2C_use_row_info_to_insert_backslash+newline?= =?utf-8?q?=2E?= Message-ID: <3fXVvb64Qkz7N8D@mail.python.org> http://hg.python.org/cpython/rev/24b4cd5695d9 changeset: 89353:24b4cd5695d9 branch: 3.3 parent: 89345:8d6dd02a973f user: Terry Jan Reedy date: Sun Feb 23 23:33:08 2014 -0500 summary: Issue #9974: When untokenizing, use row info to insert backslash+newline. Original patches by A. Kuchling and G. Rees (#12691). files: Lib/test/test_tokenize.py | 17 ++++++++++++++++- Lib/tokenize.py | 6 ++++++ 2 files changed, 22 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -2,7 +2,7 @@ Tests for the tokenize module. The tests can be really simple. Given a small fragment of source -code, print out a table with tokens. The ENDMARK is omitted for +code, print out a table with tokens. The ENDMARKER is omitted for brevity. >>> dump_tokens("1 + 1") @@ -1180,6 +1180,7 @@ class UntokenizeTest(TestCase): def test_bad_input_order(self): + # raise if previous row u = Untokenizer() u.prev_row = 2 u.prev_col = 2 @@ -1187,8 +1188,22 @@ u.add_whitespace((1,3)) self.assertEqual(cm.exception.args[0], 'start (1,3) precedes previous end (2,2)') + # raise if previous column in row self.assertRaises(ValueError, u.add_whitespace, (2,1)) + def test_backslash_continuation(self): + # The problem is that \ leaves no token + u = Untokenizer() + u.prev_row = 1 + u.prev_col = 1 + u.tokens = [] + u.add_whitespace((2, 0)) + self.assertEqual(u.tokens, ['\\\n']) + u.prev_row = 2 + u.add_whitespace((4, 4)) + self.assertEqual(u.tokens, ['\\\n', '\\\n\\\n', ' ']) + self.assertTrue(roundtrip('a\n b\n c\n \\\n c\n')) + def test_iter_compat(self): u = Untokenizer() token = (NAME, 'Hello') diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -234,6 +234,10 @@ if row < self.prev_row or row == self.prev_row and col < self.prev_col: raise ValueError("start ({},{}) precedes previous end ({},{})" .format(row, col, self.prev_row, self.prev_col)) + row_offset = row - self.prev_row + if row_offset: + self.tokens.append("\\\n" * row_offset) + self.prev_col = 0 col_offset = col - self.prev_col if col_offset: self.tokens.append(" " * col_offset) @@ -248,6 +252,8 @@ if tok_type == ENCODING: self.encoding = token continue + if tok_type == ENDMARKER: + break self.add_whitespace(start) self.tokens.append(token) self.prev_row, self.prev_col = end -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 05:40:45 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 24 Feb 2014 05:40:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3fXVvd19smz7N9V@mail.python.org> http://hg.python.org/cpython/rev/5ff0013a6e4e changeset: 89354:5ff0013a6e4e parent: 89351:b34b34d3c5ad parent: 89353:24b4cd5695d9 user: Terry Jan Reedy date: Sun Feb 23 23:33:44 2014 -0500 summary: Merge with 3.3 files: Lib/test/test_tokenize.py | 17 ++++++++++++++++- Lib/tokenize.py | 6 ++++++ 2 files changed, 22 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -2,7 +2,7 @@ Tests for the tokenize module. The tests can be really simple. Given a small fragment of source -code, print out a table with tokens. The ENDMARK is omitted for +code, print out a table with tokens. The ENDMARKER is omitted for brevity. >>> dump_tokens("1 + 1") @@ -1180,6 +1180,7 @@ class UntokenizeTest(TestCase): def test_bad_input_order(self): + # raise if previous row u = Untokenizer() u.prev_row = 2 u.prev_col = 2 @@ -1187,8 +1188,22 @@ u.add_whitespace((1,3)) self.assertEqual(cm.exception.args[0], 'start (1,3) precedes previous end (2,2)') + # raise if previous column in row self.assertRaises(ValueError, u.add_whitespace, (2,1)) + def test_backslash_continuation(self): + # The problem is that \ leaves no token + u = Untokenizer() + u.prev_row = 1 + u.prev_col = 1 + u.tokens = [] + u.add_whitespace((2, 0)) + self.assertEqual(u.tokens, ['\\\n']) + u.prev_row = 2 + u.add_whitespace((4, 4)) + self.assertEqual(u.tokens, ['\\\n', '\\\n\\\n', ' ']) + self.assertTrue(roundtrip('a\n b\n c\n \\\n c\n')) + def test_iter_compat(self): u = Untokenizer() token = (NAME, 'Hello') diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -234,6 +234,10 @@ if row < self.prev_row or row == self.prev_row and col < self.prev_col: raise ValueError("start ({},{}) precedes previous end ({},{})" .format(row, col, self.prev_row, self.prev_col)) + row_offset = row - self.prev_row + if row_offset: + self.tokens.append("\\\n" * row_offset) + self.prev_col = 0 col_offset = col - self.prev_col if col_offset: self.tokens.append(" " * col_offset) @@ -248,6 +252,8 @@ if tok_type == ENCODING: self.encoding = token continue + if tok_type == ENDMARKER: + break self.add_whitespace(start) self.tokens.append(token) self.prev_row, self.prev_col = end -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 05:40:46 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 24 Feb 2014 05:40:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_whitespace?= Message-ID: <3fXVvf3t4lz7N7g@mail.python.org> http://hg.python.org/cpython/rev/eb3c819f4841 changeset: 89355:eb3c819f4841 branch: 3.3 parent: 89353:24b4cd5695d9 user: Terry Jan Reedy date: Sun Feb 23 23:39:57 2014 -0500 summary: whitespace files: Lib/tokenize.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -235,7 +235,7 @@ raise ValueError("start ({},{}) precedes previous end ({},{})" .format(row, col, self.prev_row, self.prev_col)) row_offset = row - self.prev_row - if row_offset: + if row_offset: self.tokens.append("\\\n" * row_offset) self.prev_col = 0 col_offset = col - self.prev_col -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 05:40:47 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 24 Feb 2014 05:40:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3fXVvg6YYNz7N8h@mail.python.org> http://hg.python.org/cpython/rev/a91e50feeac4 changeset: 89356:a91e50feeac4 parent: 89354:5ff0013a6e4e parent: 89355:eb3c819f4841 user: Terry Jan Reedy date: Sun Feb 23 23:40:16 2014 -0500 summary: Merge with 3.3 files: Lib/tokenize.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -235,7 +235,7 @@ raise ValueError("start ({},{}) precedes previous end ({},{})" .format(row, col, self.prev_row, self.prev_col)) row_offset = row - self.prev_row - if row_offset: + if row_offset: self.tokens.append("\\\n" * row_offset) self.prev_col = 0 col_offset = col - self.prev_col -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Feb 24 08:13:56 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 24 Feb 2014 08:13:56 +0100 Subject: [Python-checkins] Daily reference leaks (73aa6d672b81): sum=0 Message-ID: results for 73aa6d672b81 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogQpbMR4', '-x'] From python-checkins at python.org Mon Feb 24 09:26:27 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 24 Feb 2014 09:26:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogQ2xvc2VzICMyMDcz?= =?utf-8?q?5=3A_remove_erroneous_deprecated_marker_from_stringprep_docs?= Message-ID: <3fXbw326WSz7Mj0@mail.python.org> http://hg.python.org/cpython/rev/de5d4a60ab95 changeset: 89357:de5d4a60ab95 branch: 3.3 parent: 89355:eb3c819f4841 user: Georg Brandl date: Mon Feb 24 09:26:53 2014 +0100 summary: Closes #20735: remove erroneous deprecated marker from stringprep docs files: Doc/library/stringprep.rst | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Doc/library/stringprep.rst b/Doc/library/stringprep.rst --- a/Doc/library/stringprep.rst +++ b/Doc/library/stringprep.rst @@ -3,7 +3,6 @@ .. module:: stringprep :synopsis: String preparation, as per RFC 3453 - :deprecated: .. moduleauthor:: Martin v. L?wis .. sectionauthor:: Martin v. L?wis -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 09:26:28 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 24 Feb 2014 09:26:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge_with_3=2E3?= Message-ID: <3fXbw43nMYz7N8x@mail.python.org> http://hg.python.org/cpython/rev/6e240b661ab5 changeset: 89358:6e240b661ab5 parent: 89356:a91e50feeac4 parent: 89357:de5d4a60ab95 user: Georg Brandl date: Mon Feb 24 09:27:16 2014 +0100 summary: merge with 3.3 files: Doc/library/stringprep.rst | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Doc/library/stringprep.rst b/Doc/library/stringprep.rst --- a/Doc/library/stringprep.rst +++ b/Doc/library/stringprep.rst @@ -3,7 +3,6 @@ .. module:: stringprep :synopsis: String preparation, as per RFC 3453 - :deprecated: .. moduleauthor:: Martin v. L?wis .. sectionauthor:: Martin v. L?wis -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 09:34:22 2014 From: python-checkins at python.org (georg.brandl) Date: Mon, 24 Feb 2014 09:34:22 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogQ2xvc2VzICMyMDc1?= =?utf-8?q?5=3A_port_sphinx-1=2E1_fixes_from_default?= Message-ID: <3fXc5B30dFz7Mj0@mail.python.org> http://hg.python.org/cpython/rev/7358ca69f351 changeset: 89359:7358ca69f351 branch: 3.3 parent: 89357:de5d4a60ab95 user: Georg Brandl date: Mon Feb 24 09:35:07 2014 +0100 summary: Closes #20755: port sphinx-1.1 fixes from default files: Doc/tools/sphinxext/pyspecific.py | 22 +++++++++--------- 1 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Doc/tools/sphinxext/pyspecific.py b/Doc/tools/sphinxext/pyspecific.py --- a/Doc/tools/sphinxext/pyspecific.py +++ b/Doc/tools/sphinxext/pyspecific.py @@ -16,6 +16,7 @@ import sphinx from sphinx.util.nodes import split_explicit_title +from sphinx.util.compat import Directive from sphinx.writers.html import HTMLTranslator from sphinx.writers.latex import LaTeXTranslator from sphinx.locale import versionlabels @@ -27,7 +28,9 @@ Body.enum.converters['lowerroman'] = \ Body.enum.converters['upperroman'] = lambda x: None -if sphinx.__version__[:3] < '1.2': +SPHINX11 = sphinx.__version__[:3] < '1.2' + +if SPHINX11: # monkey-patch HTML translator to give versionmodified paragraphs a class def new_visit_versionmodified(self, node): self.body.append(self.starttag(node, 'p', CLASS=node['type'])) @@ -88,8 +91,6 @@ # Support for marking up implementation details -from sphinx.util.compat import Directive - class ImplementationDetail(Directive): has_content = True @@ -142,10 +143,6 @@ # Support for documenting version of removal in deprecations -from sphinx.locale import versionlabels -from sphinx.util.compat import Directive - - class DeprecatedRemoved(Directive): has_content = True required_arguments = 2 @@ -171,16 +168,16 @@ messages = [] if self.content: self.state.nested_parse(self.content, self.content_offset, node) - if len(node): if isinstance(node[0], nodes.paragraph) and node[0].rawsource: content = nodes.inline(node[0].rawsource, translatable=True) content.source = node[0].source content.line = node[0].line content += node[0].children node[0].replace_self(nodes.paragraph('', '', content)) - node[0].insert(0, nodes.inline('', '%s: ' % text, - classes=['versionmodified'])) - else: + if not SPHINX11: + node[0].insert(0, nodes.inline('', '%s: ' % text, + classes=['versionmodified'])) + elif not SPHINX11: para = nodes.paragraph('', '', nodes.inline('', '%s.' % text, classes=['versionmodified'])) node.append(para) @@ -188,6 +185,9 @@ env.note_versionchange('deprecated', version[0], node, self.lineno) return [node] + messages +# for Sphinx < 1.2 +versionlabels['deprecated-removed'] = DeprecatedRemoved._label + # Support for including Misc/NEWS -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 12:47:06 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 24 Feb 2014 12:47:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <3fXhMZ4gwlz7Ljm@mail.python.org> http://hg.python.org/cpython/rev/cd9403fca648 changeset: 89360:cd9403fca648 parent: 89358:6e240b661ab5 parent: 89359:7358ca69f351 user: Serhiy Storchaka date: Mon Feb 24 13:46:21 2014 +0200 summary: Null merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 13:01:55 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 24 Feb 2014 13:01:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTM1?= =?utf-8?q?=3A_PYTHONWARNING_no_longer_affects_the_run=5Ftests=2Epy_script?= =?utf-8?q?=2E?= Message-ID: <3fXhhg0lFYz7NC2@mail.python.org> http://hg.python.org/cpython/rev/c89e495cdff8 changeset: 89361:c89e495cdff8 branch: 3.3 parent: 89359:7358ca69f351 user: Serhiy Storchaka date: Mon Feb 24 13:57:00 2014 +0200 summary: Issue #20535: PYTHONWARNING no longer affects the run_tests.py script. Patch by Arfrever Frehtes Taifersar Arahesis. files: Misc/NEWS | 6 ++++++ Tools/scripts/run_tests.py | 6 ++++++ 2 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -149,6 +149,12 @@ - Issue #20609: Restored the ability to build 64-bit Windows binaries on 32-bit Windows, which was broken by the change in issue #19788. +Tools/Demos +----------- + +- Issue #20535: PYTHONWARNING no longer affects the run_tests.py script. + Patch by Arfrever Frehtes Taifersar Arahesis. + What's New in Python 3.3.4? =========================== diff --git a/Tools/scripts/run_tests.py b/Tools/scripts/run_tests.py --- a/Tools/scripts/run_tests.py +++ b/Tools/scripts/run_tests.py @@ -32,6 +32,12 @@ ] # Allow user-specified interpreter options to override our defaults. args.extend(test.support.args_from_interpreter_flags()) + + # Workaround for issue #20355 + os.environ.pop("PYTHONWARNINGS", None) + # Workaround for issue #20361 + args.extend(['-W', 'error::BytesWarning']) + args.extend(['-m', 'test', # Run the test suite '-r', # Randomize test order '-w', # Re-run failed tests in verbose mode -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 13:01:56 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 24 Feb 2014 13:01:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320535=3A_PYTHONWARNING_no_longer_affects_the_ru?= =?utf-8?q?n=5Ftests=2Epy_script=2E?= Message-ID: <3fXhhh2XKvz7NBw@mail.python.org> http://hg.python.org/cpython/rev/656d0e273ccb changeset: 89362:656d0e273ccb parent: 89360:cd9403fca648 parent: 89361:c89e495cdff8 user: Serhiy Storchaka date: Mon Feb 24 14:00:38 2014 +0200 summary: Issue #20535: PYTHONWARNING no longer affects the run_tests.py script. Patch by Arfrever Frehtes Taifersar Arahesis. files: Misc/NEWS | 6 ++++++ Tools/scripts/run_tests.py | 6 ++++++ 2 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,12 @@ - Issue #20743: Fix a reference leak in test_tcl. +Tools/Demos +----------- + +- Issue #20535: PYTHONWARNING no longer affects the run_tests.py script. + Patch by Arfrever Frehtes Taifersar Arahesis. + What's New in Python 3.4.0 release candidate 2? =============================================== diff --git a/Tools/scripts/run_tests.py b/Tools/scripts/run_tests.py --- a/Tools/scripts/run_tests.py +++ b/Tools/scripts/run_tests.py @@ -32,6 +32,12 @@ ] # Allow user-specified interpreter options to override our defaults. args.extend(test.support.args_from_interpreter_flags()) + + # Workaround for issue #20355 + os.environ.pop("PYTHONWARNINGS", None) + # Workaround for issue #20361 + args.extend(['-W', 'error::BytesWarning']) + args.extend(['-m', 'test', # Run the test suite '-r', # Randomize test order '-w', # Re-run failed tests in verbose mode -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 13:19:35 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 24 Feb 2014 13:19:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_subprocess=2EPopen=2Ewait_?= =?utf-8?q?doc=3A_mention_asyncio_to_avoid_busy_loop?= Message-ID: <3fXj534M6Mz7Ljm@mail.python.org> http://hg.python.org/cpython/rev/e82e1dd7c5b2 changeset: 89363:e82e1dd7c5b2 user: Victor Stinner date: Mon Feb 24 13:18:47 2014 +0100 summary: subprocess.Popen.wait doc: mention asyncio to avoid busy loop files: Doc/library/subprocess.rst | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -629,6 +629,12 @@ :exc:`TimeoutExpired` exception. It is safe to catch this exception and retry the wait. + .. note:: + + The function is implemented using a busy loop (non-blocking call and + short sleeps). Use the :mod:`asyncio` module for an asynchronous wait: + see :class:`asyncio.create_subprocess_exec`. + .. warning:: This will deadlock when using ``stdout=PIPE`` and/or -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 13:19:36 2014 From: python-checkins at python.org (victor.stinner) Date: Mon, 24 Feb 2014 13:19:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio_doc=3A_fix_referen?= =?utf-8?q?ces_in_subprocess_doc?= Message-ID: <3fXj5463trz7Ljm@mail.python.org> http://hg.python.org/cpython/rev/768013d59a70 changeset: 89364:768013d59a70 user: Victor Stinner date: Mon Feb 24 13:19:19 2014 +0100 summary: asyncio doc: fix references in subprocess doc files: Doc/library/asyncio-subprocess.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -8,14 +8,14 @@ .. function:: create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds) - Run the shell command *cmd* given as a string. Return a :class:`Process` + Run the shell command *cmd* given as a string. Return a :class:`~asyncio.subprocess.Process` instance. This function returns a :ref:`coroutine object `. .. function:: create_subprocess_exec(\*args, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds) - Create a subprocess. Return a :class:`Process` instance. + Create a subprocess. Return a :class:`~asyncio.subprocess.Process` instance. This function returns a :ref:`coroutine object `. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 14:00:11 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 24 Feb 2014 14:00:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE5NjE5?= =?utf-8?q?=3A_Blacklist_non-text_codecs_in_method_API?= Message-ID: <3fXjzv0Rzrz7NBG@mail.python.org> http://hg.python.org/cpython/rev/95386bbf9471 changeset: 89365:95386bbf9471 branch: 3.3 parent: 89361:c89e495cdff8 user: Serhiy Storchaka date: Mon Feb 24 14:43:03 2014 +0200 summary: Issue #19619: Blacklist non-text codecs in method API str.encode, bytes.decode and bytearray.decode now use an internal API to throw LookupError for known non-text encodings, rather than attempting the encoding or decoding operation and then throwing a TypeError for an unexpected output type. The latter mechanism remains in place for third party non-text encodings. Backported changeset d68df99d7a57. files: Include/codecs.h | 27 ++++ Lib/codecs.py | 14 ++- Lib/encodings/base64_codec.py | 1 + Lib/encodings/bz2_codec.py | 1 + Lib/encodings/hex_codec.py | 1 + Lib/encodings/quopri_codec.py | 1 + Lib/encodings/rot_13.py | 1 + Lib/encodings/uu_codec.py | 1 + Lib/encodings/zlib_codec.py | 1 + Lib/test/test_codecs.py | 42 ++++++ Misc/NEWS | 6 + Objects/unicodeobject.c | 4 +- Python/codecs.c | 138 +++++++++++++++++++-- 13 files changed, 219 insertions(+), 19 deletions(-) diff --git a/Include/codecs.h b/Include/codecs.h --- a/Include/codecs.h +++ b/Include/codecs.h @@ -94,6 +94,33 @@ const char *errors ); +#ifndef PY_LIMITED_API +/* Text codec specific encoding and decoding API. + + Checks the encoding against a list of codecs which do not + implement a str<->bytes encoding before attempting the + operation. + + Please note that these APIs are internal and should not + be used in Python C extensions. + + */ + +PyAPI_FUNC(PyObject *) _PyCodec_EncodeText( + PyObject *object, + const char *encoding, + const char *errors + ); + +PyAPI_FUNC(PyObject *) _PyCodec_DecodeText( + PyObject *object, + const char *encoding, + const char *errors + ); +#endif + + + /* --- Codec Lookup APIs -------------------------------------------------- All APIs return a codec object with incremented refcount and are diff --git a/Lib/codecs.py b/Lib/codecs.py --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -73,9 +73,19 @@ ### Codec base classes (defining the API) class CodecInfo(tuple): + """Codec details when looking up the codec registry""" + + # Private API to allow Python 3.4 to blacklist the known non-Unicode + # codecs in the standard library. A more general mechanism to + # reliably distinguish test encodings from other codecs will hopefully + # be defined for Python 3.5 + # + # See http://bugs.python.org/issue19619 + _is_text_encoding = True # Assume codecs are text encodings by default def __new__(cls, encode, decode, streamreader=None, streamwriter=None, - incrementalencoder=None, incrementaldecoder=None, name=None): + incrementalencoder=None, incrementaldecoder=None, name=None, + *, _is_text_encoding=None): self = tuple.__new__(cls, (encode, decode, streamreader, streamwriter)) self.name = name self.encode = encode @@ -84,6 +94,8 @@ self.incrementaldecoder = incrementaldecoder self.streamwriter = streamwriter self.streamreader = streamreader + if _is_text_encoding is not None: + self._is_text_encoding = _is_text_encoding return self def __repr__(self): diff --git a/Lib/encodings/base64_codec.py b/Lib/encodings/base64_codec.py --- a/Lib/encodings/base64_codec.py +++ b/Lib/encodings/base64_codec.py @@ -52,4 +52,5 @@ incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, + _is_text_encoding=False, ) diff --git a/Lib/encodings/bz2_codec.py b/Lib/encodings/bz2_codec.py --- a/Lib/encodings/bz2_codec.py +++ b/Lib/encodings/bz2_codec.py @@ -74,4 +74,5 @@ incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, + _is_text_encoding=False, ) diff --git a/Lib/encodings/hex_codec.py b/Lib/encodings/hex_codec.py --- a/Lib/encodings/hex_codec.py +++ b/Lib/encodings/hex_codec.py @@ -52,4 +52,5 @@ incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, + _is_text_encoding=False, ) diff --git a/Lib/encodings/quopri_codec.py b/Lib/encodings/quopri_codec.py --- a/Lib/encodings/quopri_codec.py +++ b/Lib/encodings/quopri_codec.py @@ -53,4 +53,5 @@ incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, + _is_text_encoding=False, ) diff --git a/Lib/encodings/rot_13.py b/Lib/encodings/rot_13.py --- a/Lib/encodings/rot_13.py +++ b/Lib/encodings/rot_13.py @@ -43,6 +43,7 @@ incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader, + _is_text_encoding=False, ) ### Map diff --git a/Lib/encodings/uu_codec.py b/Lib/encodings/uu_codec.py --- a/Lib/encodings/uu_codec.py +++ b/Lib/encodings/uu_codec.py @@ -96,4 +96,5 @@ incrementaldecoder=IncrementalDecoder, streamreader=StreamReader, streamwriter=StreamWriter, + _is_text_encoding=False, ) diff --git a/Lib/encodings/zlib_codec.py b/Lib/encodings/zlib_codec.py --- a/Lib/encodings/zlib_codec.py +++ b/Lib/encodings/zlib_codec.py @@ -74,4 +74,5 @@ incrementaldecoder=IncrementalDecoder, streamreader=StreamReader, streamwriter=StreamWriter, + _is_text_encoding=False, ) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -4,6 +4,7 @@ import sys import unittest import warnings +import encodings from test import support @@ -2408,6 +2409,47 @@ sout = reader.readline() self.assertEqual(sout, b"\x80") + def test_text_to_binary_blacklists_binary_transforms(self): + # Check binary -> binary codecs give a good error for str input + bad_input = "bad input type" + for encoding in bytes_transform_encodings: + fmt = (r"{!r} is not a text encoding; " + r"use codecs.encode\(\) to handle arbitrary codecs") + msg = fmt.format(encoding) + with self.assertRaisesRegex(LookupError, msg) as failure: + bad_input.encode(encoding) + self.assertIsNone(failure.exception.__cause__) + + def test_text_to_binary_blacklists_text_transforms(self): + # Check str.encode gives a good error message for str -> str codecs + msg = (r"^'rot_13' is not a text encoding; " + r"use codecs.encode\(\) to handle arbitrary codecs") + with self.assertRaisesRegex(LookupError, msg): + "just an example message".encode("rot_13") + + def test_binary_to_text_blacklists_binary_transforms(self): + # Check bytes.decode and bytearray.decode give a good error + # message for binary -> binary codecs + data = b"encode first to ensure we meet any format restrictions" + for encoding in bytes_transform_encodings: + encoded_data = codecs.encode(data, encoding) + fmt = (r"{!r} is not a text encoding; " + r"use codecs.decode\(\) to handle arbitrary codecs") + msg = fmt.format(encoding) + with self.assertRaisesRegex(LookupError, msg): + encoded_data.decode(encoding) + with self.assertRaisesRegex(LookupError, msg): + bytearray(encoded_data).decode(encoding) + + def test_binary_to_text_blacklists_text_transforms(self): + # Check str -> str codec gives a good error for binary input + for bad_input in (b"immutable", bytearray(b"mutable")): + msg = (r"^'rot_13' is not a text encoding; " + r"use codecs.decode\(\) to handle arbitrary codecs") + with self.assertRaisesRegex(LookupError, msg) as failure: + bad_input.decode("rot_13") + self.assertIsNone(failure.exception.__cause__) + @unittest.skipUnless(sys.platform == 'win32', 'code pages are specific to Windows') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,12 @@ Core and Builtins ----------------- +- Issue #19619: str.encode, bytes.decode and bytearray.decode now use an + internal API to throw LookupError for known non-text encodings, rather + than attempting the encoding or decoding operation and then throwing a + TypeError for an unexpected output type. (The latter mechanism remains + in place for third party non-text encodings) + - Issue #20588: Make Python-ast.c C89 compliant. - Issue #20437: Fixed 21 potential bugs when deleting objects references. diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3129,7 +3129,7 @@ buffer = PyMemoryView_FromBuffer(&info); if (buffer == NULL) goto onError; - unicode = PyCodec_Decode(buffer, encoding, errors); + unicode = _PyCodec_DecodeText(buffer, encoding, errors); if (unicode == NULL) goto onError; if (!PyUnicode_Check(unicode)) { @@ -3489,7 +3489,7 @@ } /* Encode via the codec registry */ - v = PyCodec_Encode(unicode, encoding, errors); + v = _PyCodec_EncodeText(unicode, encoding, errors); if (v == NULL) return NULL; diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -337,18 +337,15 @@ errors is passed to the encoder factory as argument if non-NULL. */ -PyObject *PyCodec_Encode(PyObject *object, - const char *encoding, - const char *errors) +static PyObject * +_PyCodec_EncodeInternal(PyObject *object, + PyObject *encoder, + const char *encoding, + const char *errors) { - PyObject *encoder = NULL; PyObject *args = NULL, *result = NULL; PyObject *v = NULL; - encoder = PyCodec_Encoder(encoding); - if (encoder == NULL) - goto onError; - args = args_tuple(object, errors); if (args == NULL) goto onError; @@ -384,18 +381,15 @@ errors is passed to the decoder factory as argument if non-NULL. */ -PyObject *PyCodec_Decode(PyObject *object, - const char *encoding, - const char *errors) +static PyObject * +_PyCodec_DecodeInternal(PyObject *object, + PyObject *decoder, + const char *encoding, + const char *errors) { - PyObject *decoder = NULL; PyObject *args = NULL, *result = NULL; PyObject *v; - decoder = PyCodec_Decoder(encoding); - if (decoder == NULL) - goto onError; - args = args_tuple(object, errors); if (args == NULL) goto onError; @@ -425,6 +419,118 @@ return NULL; } +/* Generic encoding/decoding API */ +PyObject *PyCodec_Encode(PyObject *object, + const char *encoding, + const char *errors) +{ + PyObject *encoder; + + encoder = PyCodec_Encoder(encoding); + if (encoder == NULL) + return NULL; + + return _PyCodec_EncodeInternal(object, encoder, encoding, errors); +} + +PyObject *PyCodec_Decode(PyObject *object, + const char *encoding, + const char *errors) +{ + PyObject *decoder; + + decoder = PyCodec_Decoder(encoding); + if (decoder == NULL) + return NULL; + + return _PyCodec_DecodeInternal(object, decoder, encoding, errors); +} + +/* Text encoding/decoding API */ +static +PyObject *codec_getitem_checked(const char *encoding, + const char *operation_name, + int index) +{ + _Py_IDENTIFIER(_is_text_encoding); + PyObject *codec; + PyObject *attr; + PyObject *v; + int is_text_codec; + + codec = _PyCodec_Lookup(encoding); + if (codec == NULL) + return NULL; + + /* Backwards compatibility: assume any raw tuple describes a text + * encoding, and the same for anything lacking the private + * attribute. + */ + if (!PyTuple_CheckExact(codec)) { + attr = _PyObject_GetAttrId(codec, &PyId__is_text_encoding); + if (attr == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + Py_DECREF(codec); + return NULL; + } + } else { + is_text_codec = PyObject_IsTrue(attr); + Py_DECREF(attr); + if (!is_text_codec) { + Py_DECREF(codec); + PyErr_Format(PyExc_LookupError, + "'%.400s' is not a text encoding; " + "use codecs.%s() to handle arbitrary codecs", + encoding, operation_name); + return NULL; + } + } + } + + v = PyTuple_GET_ITEM(codec, index); + Py_DECREF(codec); + Py_INCREF(v); + return v; +} + +static PyObject * _PyCodec_TextEncoder(const char *encoding) +{ + return codec_getitem_checked(encoding, "encode", 0); +} + +static PyObject * _PyCodec_TextDecoder(const char *encoding) +{ + return codec_getitem_checked(encoding, "decode", 1); +} + +PyObject *_PyCodec_EncodeText(PyObject *object, + const char *encoding, + const char *errors) +{ + PyObject *encoder; + + encoder = _PyCodec_TextEncoder(encoding); + if (encoder == NULL) + return NULL; + + return _PyCodec_EncodeInternal(object, encoder, encoding, errors); +} + +PyObject *_PyCodec_DecodeText(PyObject *object, + const char *encoding, + const char *errors) +{ + PyObject *decoder; + + decoder = _PyCodec_TextDecoder(encoding); + if (decoder == NULL) + return NULL; + + return _PyCodec_DecodeInternal(object, decoder, encoding, errors); +} + /* Register the error handling callback function error under the name name. This function will be called by the codec when it encounters an unencodable characters/undecodable bytes and doesn't know the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 14:00:12 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 24 Feb 2014 14:00:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <3fXjzw2Xyxz7NBv@mail.python.org> http://hg.python.org/cpython/rev/559ced4bb682 changeset: 89366:559ced4bb682 parent: 89362:656d0e273ccb parent: 89365:95386bbf9471 user: Serhiy Storchaka date: Mon Feb 24 14:47:20 2014 +0200 summary: Null merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 14:00:13 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 24 Feb 2014 14:00:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_heads?= Message-ID: <3fXjzx3y3Wz7NBc@mail.python.org> http://hg.python.org/cpython/rev/562ed304b30e changeset: 89367:562ed304b30e parent: 89366:559ced4bb682 parent: 89364:768013d59a70 user: Serhiy Storchaka date: Mon Feb 24 14:57:35 2014 +0200 summary: Merge heads files: Doc/library/asyncio-subprocess.rst | 4 ++-- Doc/library/subprocess.rst | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst --- a/Doc/library/asyncio-subprocess.rst +++ b/Doc/library/asyncio-subprocess.rst @@ -8,14 +8,14 @@ .. function:: create_subprocess_shell(cmd, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds) - Run the shell command *cmd* given as a string. Return a :class:`Process` + Run the shell command *cmd* given as a string. Return a :class:`~asyncio.subprocess.Process` instance. This function returns a :ref:`coroutine object `. .. function:: create_subprocess_exec(\*args, stdin=None, stdout=None, stderr=None, loop=None, limit=None, \*\*kwds) - Create a subprocess. Return a :class:`Process` instance. + Create a subprocess. Return a :class:`~asyncio.subprocess.Process` instance. This function returns a :ref:`coroutine object `. diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -629,6 +629,12 @@ :exc:`TimeoutExpired` exception. It is safe to catch this exception and retry the wait. + .. note:: + + The function is implemented using a busy loop (non-blocking call and + short sleeps). Use the :mod:`asyncio` module for an asynchronous wait: + see :class:`asyncio.create_subprocess_exec`. + .. warning:: This will deadlock when using ``stdout=PIPE`` and/or -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 17:01:44 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 17:01:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_frame=2Eclear?= =?utf-8?q?=2C_expanded_entry_for_-I/isolated_mode=2E?= Message-ID: <3fXp1N2Y7Kz7N9L@mail.python.org> http://hg.python.org/cpython/rev/50c74ff29894 changeset: 89368:50c74ff29894 user: R David Murray date: Mon Feb 24 10:38:13 2014 -0500 summary: whatsnew: frame.clear, expanded entry for -I/isolated mode. files: Doc/whatsnew/3.4.rst | 22 ++++++++++++++++++++-- 1 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -95,7 +95,7 @@ * :ref:`pip should always be "available" ` (:pep:`453`). * :ref:`Make newly created file descriptors non-inheritable ` (:pep:`446`). -* command line option for :ref:`isolated mode `, +* command line option for :ref:`isolated mode `, (:issue:`16499`). * :ref:`improvements in the handling of codecs ` that are not text encodings (multiple issues). @@ -373,6 +373,10 @@ method for its *base* argument. (Contributed by Mark Dickinson in :issue:`16772`.) +* Frame objects now have a :func:`~frame.clear` method that clears all + references to local variables from the frame. (Contributed by Antoine Pitrou + in :issue:`17934`.) + New Modules =========== @@ -1253,7 +1257,8 @@ A new :func:`traceback.clear_frames` function takes a traceback object and clears the local variables in all of the frames it references, -reducing the amount of memory consumed (:issue:`1565525`). +reducing the amount of memory consumed. (Contributed by Andrew Kuchling in +:issue:`1565525`). urllib @@ -1485,6 +1490,19 @@ Other Improvements ------------------ +.. _whatsnew-isolated-mode: + +* The :ref:`python ` command has a new :ref:`option + `, ``-I``, which causes it to run in "isolated mode", + which means that :data:`sys.path` contains neither the script's directory nor + the user's ``site-packages`` directory, and all :envvar:`PYTHON*` environment + variables are ignored (it implies both ``-s`` and ``-E``). Other + restrictions may also be applied in the future, with the goal being to + isolate the execution of a script from the user's environment. This is + appropriate, for example, when Python is used to run a system script. On + most POSIX systems it can and should be used in the ``#!`` line of system + scripts. (Contributed by Christian Heims in :issue:`16499`.) + * Tab-completion is now enabled by default in the interactive interpreter. (Contributed by Antoine Pitrou and ?ric Araujo in :issue:`5845`.) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 17:01:45 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 17:01:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_NEWS_entry_wording=2E?= Message-ID: <3fXp1P4H5Sz7NCS@mail.python.org> http://hg.python.org/cpython/rev/3104c8530cf4 changeset: 89369:3104c8530cf4 user: R David Murray date: Mon Feb 24 10:42:20 2014 -0500 summary: Fix NEWS entry wording. files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1862,7 +1862,7 @@ - Issue #18808: Non-daemon threads are now automatically joined when a sub-interpreter is shutdown (it would previously dump a fatal error). -- Remove supporting for compiling on systems without getcwd(). +- Remove support for compiling on systems without getcwd(). - Issue #18774: Remove last bits of GNU PTH thread code and thread_pth.h. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 17:01:46 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 17:01:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Remove_redundant_NEWS_entr?= =?utf-8?q?y=2E?= Message-ID: <3fXp1Q5n91z7NCy@mail.python.org> http://hg.python.org/cpython/rev/879fb0718487 changeset: 89370:879fb0718487 user: R David Murray date: Mon Feb 24 10:55:08 2014 -0500 summary: Remove redundant NEWS entry. files: Misc/NEWS | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1848,9 +1848,6 @@ - Issue #18942: sys._debugmallocstats() output was damaged on Windows. -- Issue #18780: %-formatting now prints value instead of str for - int subclasses when using %d, %i, and %u codes. - - Issue #18571: Implementation of the PEP 446: file descriptors and file handles are now created non-inheritable; add functions os.get/set_inheritable(), os.get/set_handle_inheritable() and -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 18:59:37 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 18:59:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_typo=2E?= Message-ID: <3fXrdP4DZtz7NCw@mail.python.org> http://hg.python.org/cpython/rev/718cddfa0292 changeset: 89371:718cddfa0292 user: R David Murray date: Mon Feb 24 12:59:20 2014 -0500 summary: Fix typo. files: Doc/whatsnew/3.4.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1501,7 +1501,7 @@ isolate the execution of a script from the user's environment. This is appropriate, for example, when Python is used to run a system script. On most POSIX systems it can and should be used in the ``#!`` line of system - scripts. (Contributed by Christian Heims in :issue:`16499`.) + scripts. (Contributed by Christian Heimes in :issue:`16499`.) * Tab-completion is now enabled by default in the interactive interpreter. (Contributed by Antoine Pitrou and ?ric Araujo in :issue:`5845`.) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 20:00:00 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 24 Feb 2014 20:00:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzIwNzQwOiBkZXNx?= =?utf-8?q?uarify_2=2E?= Message-ID: <3fXsz44Kdjz7NDZ@mail.python.org> http://hg.python.org/cpython/rev/151a498c55e3 changeset: 89372:151a498c55e3 branch: 3.3 parent: 89365:95386bbf9471 user: Ezio Melotti date: Mon Feb 24 20:58:31 2014 +0200 summary: #20740: desquarify 2. files: Doc/tutorial/introduction.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -371,9 +371,9 @@ comma-separated values (items) between square brackets. Lists might contain items of different types, but usually the items all have the same type. :: - >>> squares = [1, 2, 4, 9, 16, 25] + >>> squares = [1, 4, 9, 16, 25] >>> squares - [1, 2, 4, 9, 16, 25] + [1, 4, 9, 16, 25] Like strings (and all other built-in :term:`sequence` type), lists can be indexed and sliced:: @@ -389,12 +389,12 @@ means that the following slice returns a new (shallow) copy of the list:: >>> squares[:] - [1, 2, 4, 9, 16, 25] + [1, 4, 9, 16, 25] Lists also supports operations like concatenation:: >>> squares + [36, 49, 64, 81, 100] - [1, 2, 4, 9, 16, 25, 36, 49, 64, 81, 100] + [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] Unlike strings, which are :term:`immutable`, lists are a :term:`mutable` type, i.e. it is possible to change their content:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 20:00:01 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 24 Feb 2014 20:00:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzIwNzQwOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3fXsz573zdz7NDm@mail.python.org> http://hg.python.org/cpython/rev/1bc585ba5df2 changeset: 89373:1bc585ba5df2 parent: 89371:718cddfa0292 parent: 89372:151a498c55e3 user: Ezio Melotti date: Mon Feb 24 20:59:48 2014 +0200 summary: #20740: merge with 3.3. files: Doc/tutorial/introduction.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -371,9 +371,9 @@ comma-separated values (items) between square brackets. Lists might contain items of different types, but usually the items all have the same type. :: - >>> squares = [1, 2, 4, 9, 16, 25] + >>> squares = [1, 4, 9, 16, 25] >>> squares - [1, 2, 4, 9, 16, 25] + [1, 4, 9, 16, 25] Like strings (and all other built-in :term:`sequence` type), lists can be indexed and sliced:: @@ -389,12 +389,12 @@ means that the following slice returns a new (shallow) copy of the list:: >>> squares[:] - [1, 2, 4, 9, 16, 25] + [1, 4, 9, 16, 25] Lists also supports operations like concatenation:: >>> squares + [36, 49, 64, 81, 100] - [1, 2, 4, 9, 16, 25, 36, 49, 64, 81, 100] + [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] Unlike strings, which are :term:`immutable`, lists are a :term:`mutable` type, i.e. it is possible to change their content:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 21:37:25 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 21:37:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzIwNjI4OiBtYWtl?= =?utf-8?q?_it_clear_that_DictReader/Writer_*fieldnames*_is_a_Sequence=2E?= Message-ID: <3fXw7T56PWz7N5f@mail.python.org> http://hg.python.org/cpython/rev/a5d4660c6cb6 changeset: 89374:a5d4660c6cb6 branch: 3.3 parent: 89372:151a498c55e3 user: R David Murray date: Mon Feb 24 15:29:22 2014 -0500 summary: #20628: make it clear that DictReader/Writer *fieldnames* is a Sequence. Patch by Sean Rodman. files: Doc/library/csv.rst | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -145,7 +145,10 @@ .. class:: DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds) Create an object which operates like a regular reader but maps the information - read into a dict whose keys are given by the optional *fieldnames* parameter. + read into a dict whose keys are given by the optional *fieldnames* parameter. + The *fieldnames* parameter is a :mod:`sequence ` whose elements + are associated with the fields of the input data in order. These elements + become the keys of the resulting dictionary. If the *fieldnames* parameter is omitted, the values in the first row of the *csvfile* will be used as the fieldnames. If the row read has more fields than the fieldnames sequence, the remaining data is added as a sequence @@ -158,7 +161,8 @@ .. class:: DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds) Create an object which operates like a regular writer but maps dictionaries onto - output rows. The *fieldnames* parameter identifies the order in which values in + output rows. The *fieldnames* parameter is a :mod:`sequence + ` of keys that identify the order in which values in the dictionary passed to the :meth:`writerow` method are written to the *csvfile*. The optional *restval* parameter specifies the value to be written if the dictionary is missing a key in *fieldnames*. If the dictionary passed to -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 21:37:27 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 21:37:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzIwNjI4OiB3cmFw?= =?utf-8?q?_lines_to_=3C_80=2E?= Message-ID: <3fXw7W2LrCz7NDP@mail.python.org> http://hg.python.org/cpython/rev/9f036047187b changeset: 89375:9f036047187b branch: 3.3 user: R David Murray date: Mon Feb 24 15:32:54 2014 -0500 summary: #20628: wrap lines to < 80. files: Doc/library/csv.rst | 61 +++++++++++++++++--------------- 1 files changed, 32 insertions(+), 29 deletions(-) diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -142,40 +142,43 @@ The :mod:`csv` module defines the following classes: -.. class:: DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds) +.. class:: DictReader(csvfile, fieldnames=None, restkey=None, restval=None, \ + dialect='excel', *args, **kwds) - Create an object which operates like a regular reader but maps the information - read into a dict whose keys are given by the optional *fieldnames* parameter. - The *fieldnames* parameter is a :mod:`sequence ` whose elements - are associated with the fields of the input data in order. These elements - become the keys of the resulting dictionary. - If the *fieldnames* parameter is omitted, the values in the first row of the - *csvfile* will be used as the fieldnames. If the row read has more fields - than the fieldnames sequence, the remaining data is added as a sequence - keyed by the value of *restkey*. If the row read has fewer fields than the - fieldnames sequence, the remaining keys take the value of the optional - *restval* parameter. Any other optional or keyword arguments are passed to - the underlying :class:`reader` instance. + Create an object which operates like a regular reader but maps the + information read into a dict whose keys are given by the optional + *fieldnames* parameter. The *fieldnames* parameter is a :mod:`sequence + ` whose elements are associated with the fields of the + input data in order. These elements become the keys of the resulting + dictionary. If the *fieldnames* parameter is omitted, the values in the + first row of the *csvfile* will be used as the fieldnames. If the row read + has more fields than the fieldnames sequence, the remaining data is added as + a sequence keyed by the value of *restkey*. If the row read has fewer + fields than the fieldnames sequence, the remaining keys take the value of + the optional *restval* parameter. Any other optional or keyword arguments + are passed to the underlying :class:`reader` instance. -.. class:: DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds) +.. class:: DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', \ + dialect='excel', *args, **kwds) - Create an object which operates like a regular writer but maps dictionaries onto - output rows. The *fieldnames* parameter is a :mod:`sequence - ` of keys that identify the order in which values in - the dictionary passed to the :meth:`writerow` method are written to the - *csvfile*. The optional *restval* parameter specifies the value to be written - if the dictionary is missing a key in *fieldnames*. If the dictionary passed to - the :meth:`writerow` method contains a key not found in *fieldnames*, the - optional *extrasaction* parameter indicates what action to take. If it is set - to ``'raise'`` a :exc:`ValueError` is raised. If it is set to ``'ignore'``, - extra values in the dictionary are ignored. Any other optional or keyword - arguments are passed to the underlying :class:`writer` instance. + Create an object which operates like a regular writer but maps dictionaries + onto output rows. The *fieldnames* parameter is a :mod:`sequence + ` of keys that identify the order in which values in the + dictionary passed to the :meth:`writerow` method are written to the + *csvfile*. The optional *restval* parameter specifies the value to be + written if the dictionary is missing a key in *fieldnames*. If the + dictionary passed to the :meth:`writerow` method contains a key not found in + *fieldnames*, the optional *extrasaction* parameter indicates what action to + take. If it is set to ``'raise'`` a :exc:`ValueError` is raised. If it is + set to ``'ignore'``, extra values in the dictionary are ignored. Any other + optional or keyword arguments are passed to the underlying :class:`writer` + instance. - Note that unlike the :class:`DictReader` class, the *fieldnames* parameter of - the :class:`DictWriter` is not optional. Since Python's :class:`dict` objects - are not ordered, there is not enough information available to deduce the order - in which the row should be written to the *csvfile*. + Note that unlike the :class:`DictReader` class, the *fieldnames* parameter + of the :class:`DictWriter` is not optional. Since Python's :class:`dict` + objects are not ordered, there is not enough information available to deduce + the order in which the row should be written to the *csvfile*. .. class:: Dialect -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 21:37:28 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 21:37:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_=2320628=3A_make_it_clear_that_DictReader/Writer_*?= =?utf-8?q?fieldnames*_is_a_Sequence=2E?= Message-ID: <3fXw7X6dccz7Mj3@mail.python.org> http://hg.python.org/cpython/rev/5eb7e29df762 changeset: 89376:5eb7e29df762 parent: 89373:1bc585ba5df2 parent: 89375:9f036047187b user: R David Murray date: Mon Feb 24 15:34:48 2014 -0500 summary: Merge #20628: make it clear that DictReader/Writer *fieldnames* is a Sequence. Including the subsequent line re-wrapping. files: Doc/library/csv.rst | 57 ++++++++++++++++++-------------- 1 files changed, 32 insertions(+), 25 deletions(-) diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -142,36 +142,43 @@ The :mod:`csv` module defines the following classes: -.. class:: DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds) +.. class:: DictReader(csvfile, fieldnames=None, restkey=None, restval=None, \ + dialect='excel', *args, **kwds) - Create an object which operates like a regular reader but maps the information - read into a dict whose keys are given by the optional *fieldnames* parameter. - If the *fieldnames* parameter is omitted, the values in the first row of the - *csvfile* will be used as the fieldnames. If the row read has more fields - than the fieldnames sequence, the remaining data is added as a sequence - keyed by the value of *restkey*. If the row read has fewer fields than the - fieldnames sequence, the remaining keys take the value of the optional - *restval* parameter. Any other optional or keyword arguments are passed to - the underlying :class:`reader` instance. + Create an object which operates like a regular reader but maps the + information read into a dict whose keys are given by the optional + *fieldnames* parameter. The *fieldnames* parameter is a :mod:`sequence + ` whose elements are associated with the fields of the + input data in order. These elements become the keys of the resulting + dictionary. If the *fieldnames* parameter is omitted, the values in the + first row of the *csvfile* will be used as the fieldnames. If the row read + has more fields than the fieldnames sequence, the remaining data is added as + a sequence keyed by the value of *restkey*. If the row read has fewer + fields than the fieldnames sequence, the remaining keys take the value of + the optional *restval* parameter. Any other optional or keyword arguments + are passed to the underlying :class:`reader` instance. -.. class:: DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds) +.. class:: DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', \ + dialect='excel', *args, **kwds) - Create an object which operates like a regular writer but maps dictionaries onto - output rows. The *fieldnames* parameter identifies the order in which values in - the dictionary passed to the :meth:`writerow` method are written to the - *csvfile*. The optional *restval* parameter specifies the value to be written - if the dictionary is missing a key in *fieldnames*. If the dictionary passed to - the :meth:`writerow` method contains a key not found in *fieldnames*, the - optional *extrasaction* parameter indicates what action to take. If it is set - to ``'raise'`` a :exc:`ValueError` is raised. If it is set to ``'ignore'``, - extra values in the dictionary are ignored. Any other optional or keyword - arguments are passed to the underlying :class:`writer` instance. + Create an object which operates like a regular writer but maps dictionaries + onto output rows. The *fieldnames* parameter is a :mod:`sequence + ` of keys that identify the order in which values in the + dictionary passed to the :meth:`writerow` method are written to the + *csvfile*. The optional *restval* parameter specifies the value to be + written if the dictionary is missing a key in *fieldnames*. If the + dictionary passed to the :meth:`writerow` method contains a key not found in + *fieldnames*, the optional *extrasaction* parameter indicates what action to + take. If it is set to ``'raise'`` a :exc:`ValueError` is raised. If it is + set to ``'ignore'``, extra values in the dictionary are ignored. Any other + optional or keyword arguments are passed to the underlying :class:`writer` + instance. - Note that unlike the :class:`DictReader` class, the *fieldnames* parameter of - the :class:`DictWriter` is not optional. Since Python's :class:`dict` objects - are not ordered, there is not enough information available to deduce the order - in which the row should be written to the *csvfile*. + Note that unlike the :class:`DictReader` class, the *fieldnames* parameter + of the :class:`DictWriter` is not optional. Since Python's :class:`dict` + objects are not ordered, there is not enough information available to deduce + the order in which the row should be written to the *csvfile*. .. class:: Dialect -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 21:37:30 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 21:37:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzIwNjI4OiBtYWtl?= =?utf-8?q?_it_clear_that_DictReader/Writer_*fieldnames*_is_a_Sequence=2E?= Message-ID: <3fXw7Z2Hc7z7NDp@mail.python.org> http://hg.python.org/cpython/rev/0e77dd295a88 changeset: 89377:0e77dd295a88 branch: 2.7 parent: 89352:0f0e9b7d4f1d user: R David Murray date: Mon Feb 24 15:35:19 2014 -0500 summary: #20628: make it clear that DictReader/Writer *fieldnames* is a Sequence. Patch by Sean Rodman. files: Doc/library/csv.rst | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -167,7 +167,11 @@ .. class:: DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds) Create an object which operates like a regular reader but maps the information - read into a dict whose keys are given by the optional *fieldnames* parameter. + read into a dict whose keys are given by the optional *fieldnames* + parameter. The *fieldnames* parameter is a :ref:`sequence + ` whose elements are associated with the + fields of the input data in order. These elements become the keys of the + resulting dictionary. If the *fieldnames* parameter is omitted, the values in the first row of the *csvfile* will be used as the fieldnames. If the row read has more fields than the fieldnames sequence, the remaining data is added as a sequence @@ -180,7 +184,9 @@ .. class:: DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds) Create an object which operates like a regular writer but maps dictionaries onto - output rows. The *fieldnames* parameter identifies the order in which values in + output rows. The *fieldnames* parameter is a :ref:`sequence + ` of keys that identify the order in + which values in the dictionary passed to the :meth:`writerow` method are written to the *csvfile*. The optional *restval* parameter specifies the value to be written if the dictionary is missing a key in *fieldnames*. If the dictionary passed to -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 21:37:31 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 21:37:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzIwNjI4OiB3cmFw?= =?utf-8?q?_lines_to_=3C_80=2E?= Message-ID: <3fXw7b70zgz7NDq@mail.python.org> http://hg.python.org/cpython/rev/0926adcc335c changeset: 89378:0926adcc335c branch: 2.7 user: R David Murray date: Mon Feb 24 15:36:45 2014 -0500 summary: #20628: wrap lines to < 80. files: Doc/library/csv.rst | 57 ++++++++++++++++---------------- 1 files changed, 29 insertions(+), 28 deletions(-) diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -164,42 +164,43 @@ The :mod:`csv` module defines the following classes: -.. class:: DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds) +.. class:: DictReader(csvfile, fieldnames=None, restkey=None, restval=None, \ + dialect='excel', *args, **kwds) - Create an object which operates like a regular reader but maps the information - read into a dict whose keys are given by the optional *fieldnames* - parameter. The *fieldnames* parameter is a :ref:`sequence + Create an object which operates like a regular reader but maps the + information read into a dict whose keys are given by the optional + *fieldnames* parameter. The *fieldnames* parameter is a :ref:`sequence ` whose elements are associated with the fields of the input data in order. These elements become the keys of the - resulting dictionary. - If the *fieldnames* parameter is omitted, the values in the first row of the - *csvfile* will be used as the fieldnames. If the row read has more fields - than the fieldnames sequence, the remaining data is added as a sequence - keyed by the value of *restkey*. If the row read has fewer fields than the - fieldnames sequence, the remaining keys take the value of the optional - *restval* parameter. Any other optional or keyword arguments are passed to - the underlying :class:`reader` instance. + resulting dictionary. If the *fieldnames* parameter is omitted, the values + in the first row of the *csvfile* will be used as the fieldnames. If the + row read has more fields than the fieldnames sequence, the remaining data is + added as a sequence keyed by the value of *restkey*. If the row read has + fewer fields than the fieldnames sequence, the remaining keys take the value + of the optional *restval* parameter. Any other optional or keyword + arguments are passed to the underlying :class:`reader` instance. -.. class:: DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds) +.. class:: DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', \ + dialect='excel', *args, **kwds) - Create an object which operates like a regular writer but maps dictionaries onto - output rows. The *fieldnames* parameter is a :ref:`sequence + Create an object which operates like a regular writer but maps dictionaries + onto output rows. The *fieldnames* parameter is a :ref:`sequence ` of keys that identify the order in - which values in - the dictionary passed to the :meth:`writerow` method are written to the - *csvfile*. The optional *restval* parameter specifies the value to be written - if the dictionary is missing a key in *fieldnames*. If the dictionary passed to - the :meth:`writerow` method contains a key not found in *fieldnames*, the - optional *extrasaction* parameter indicates what action to take. If it is set - to ``'raise'`` a :exc:`ValueError` is raised. If it is set to ``'ignore'``, - extra values in the dictionary are ignored. Any other optional or keyword - arguments are passed to the underlying :class:`writer` instance. + which values in the dictionary passed to the :meth:`writerow` method are + written to the *csvfile*. The optional *restval* parameter specifies the + value to be written if the dictionary is missing a key in *fieldnames*. If + the dictionary passed to the :meth:`writerow` method contains a key not + found in *fieldnames*, the optional *extrasaction* parameter indicates what + action to take. If it is set to ``'raise'`` a :exc:`ValueError` is raised. + If it is set to ``'ignore'``, extra values in the dictionary are ignored. + Any other optional or keyword arguments are passed to the underlying + :class:`writer` instance. - Note that unlike the :class:`DictReader` class, the *fieldnames* parameter of - the :class:`DictWriter` is not optional. Since Python's :class:`dict` objects - are not ordered, there is not enough information available to deduce the order - in which the row should be written to the *csvfile*. + Note that unlike the :class:`DictReader` class, the *fieldnames* parameter + of the :class:`DictWriter` is not optional. Since Python's :class:`dict` + objects are not ordered, there is not enough information available to deduce + the order in which the row should be written to the *csvfile*. .. class:: Dialect -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 21:52:20 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 21:52:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_cypthon_can_be?= =?utf-8?q?_compiled_with_address_sanity_checking_enabled=2E?= Message-ID: <3fXwSh3G10z7NFS@mail.python.org> http://hg.python.org/cpython/rev/a49f02c338bc changeset: 89379:a49f02c338bc parent: 89376:5eb7e29df762 user: R David Murray date: Mon Feb 24 15:48:22 2014 -0500 summary: whatsnew: cypthon can be compiled with address sanity checking enabled. files: Doc/whatsnew/3.4.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1484,6 +1484,11 @@ existing :c:func:`PyStructSequence_InitType` function. The difference is that it returns ``0`` on success and ``-1`` on failure. +* The CPython source can now be compiled using the address sanity checking + features of recent versions of GCC and clang: the false alarms in the small + object allocator have been silenced. (Contributed by Dhiru Kholia in + :issue:`18598`.) + .. _other-improvements-3.4: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 21:52:21 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 21:52:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_wording_of_NEWS_entry?= =?utf-8?q?=2E?= Message-ID: <3fXwSj6CxQz7N6K@mail.python.org> http://hg.python.org/cpython/rev/cff76b852b0a changeset: 89380:cff76b852b0a user: R David Murray date: Mon Feb 24 15:48:31 2014 -0500 summary: Fix wording of NEWS entry. files: Misc/NEWS | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1791,9 +1791,9 @@ - Issue #19018: The heapq.merge() function no longer suppresses IndexError in the underlying iterables. -- Issue #18784: The uuid module no more attempts to load libc via ctypes.CDLL, - if all necessary functions are already found in libuuid. - Patch by Evgeny Sologubov. +- Issue #18784: The uuid module no longer attempts to load libc via ctypes.CDLL + if all the necessary functions have already been found in libuuid. Patch by + Evgeny Sologubov. - The :envvar:`PYTHONFAULTHANDLER` environment variable now only enables the faulthandler module if the variable is non-empty. Same behaviour than other -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 21:52:23 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 21:52:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_return_type_in_doc_of_?= =?utf-8?q?PyStructSequence=5FInitType2=2E?= Message-ID: <3fXwSl1mvmz7N6K@mail.python.org> http://hg.python.org/cpython/rev/3154794a9a57 changeset: 89381:3154794a9a57 user: R David Murray date: Mon Feb 24 15:51:57 2014 -0500 summary: Fix return type in doc of PyStructSequence_InitType2. files: Doc/c-api/tuple.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/c-api/tuple.rst b/Doc/c-api/tuple.rst --- a/Doc/c-api/tuple.rst +++ b/Doc/c-api/tuple.rst @@ -129,7 +129,7 @@ Initializes a struct sequence type *type* from *desc* in place. -.. c:function:: void PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) +.. c:function:: int PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) The same as ``PyStructSequence_InitType``, but returns ``0`` on success and ``-1`` on failure. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 22:14:02 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 22:14:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_unittest=2ETes?= =?utf-8?q?tCase=2EassertLogs=2E?= Message-ID: <3fXwxk6chYz7N5f@mail.python.org> http://hg.python.org/cpython/rev/1e870209e64a changeset: 89382:1e870209e64a user: R David Murray date: Mon Feb 24 16:05:57 2014 -0500 summary: whatsnew: unittest.TestCase.assertLogs. Also fix issue number in address sanity check entry. files: Doc/whatsnew/3.4.rst | 11 ++++++++++- 1 files changed, 10 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1311,6 +1311,15 @@ custom ``_removeTestAtIndex`` method. (Contributed by Tom Wardill, Matt McClure, and Andrew Svetlov in :issue:`11798`.) +A new test assertion context-manager, :meth:`~unittest.TestCase.assertLogs`, +will ensure that a given block of code emits a log message using the +:mod:`logging` module. By default the message can come from any logger and +have a priority of ``INFO`` or higher, but both the logger name and an +alternative minimum logging level may be specified. The object returned by the +context manager can be queried for the :class:`~logging.LogRecord`\ s and/or +formatted messages that were logged. (Contributed by Antoine Pitrou in +:issue:`18937`.) + venv ---- @@ -1487,7 +1496,7 @@ * The CPython source can now be compiled using the address sanity checking features of recent versions of GCC and clang: the false alarms in the small object allocator have been silenced. (Contributed by Dhiru Kholia in - :issue:`18598`.) + :issue:`18596`.) .. _other-improvements-3.4: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 23:22:53 2014 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 24 Feb 2014 23:22:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_More_typos_found_by_Tim_Tvrtk?= =?utf-8?b?b3ZpxIcu?= Message-ID: <3fXyT96r6jz7LkD@mail.python.org> http://hg.python.org/peps/rev/5f63c8a92d1c changeset: 5386:5f63c8a92d1c user: Guido van Rossum date: Mon Feb 24 14:22:46 2014 -0800 summary: More typos found by Tim Tvrtkovi?. files: pep-3156.txt | 31 +++++++++++++++++-------------- 1 files changed, 17 insertions(+), 14 deletions(-) diff --git a/pep-3156.txt b/pep-3156.txt --- a/pep-3156.txt +++ b/pep-3156.txt @@ -603,14 +603,14 @@ a default context is created it is up to the implementation to configure reasonable defaults. The reference implementation currently uses ``PROTOCOL_SSLv23`` and sets the ``OP_NO_SSLv2`` - option, calls ``set_default_verify_paths()`` and sets verify_mode + option, calls ``set_default_verify_paths()`` and sets ``verify_mode`` to ``CERT_REQUIRED``. In addition, whenever the context (default - or otherwise) specifies a verify_mode of ``CERT_REQUIRED`` or + or otherwise) specifies a ``verify_mode`` of ``CERT_REQUIRED`` or ``CERT_OPTIONAL``, if a hostname is given, immediately after a successful handshake ``ssl.match_hostname(peercert, hostname)`` is called, and if this raises an exception the conection is closed. - (To avoid this behavior, pass in an SSL context that ha - verify_mode set to ``CERT_NONE``. But this means you are not + (To avoid this behavior, pass in an SSL context that has + ``verify_mode`` set to ``CERT_NONE``. But this means you are not secure, and vulnerable to for example man-in-the-middle attacks.) - ``family``, ``proto``, ``flags``: Address family, protocol and @@ -899,7 +899,7 @@ ``sig`` is received, arrange for ``callback(*args)`` to be called. Specifying another callback for the same signal replaces the previous handler (only one handler can be active per signal). The - ``sig`` must be a valid sigal number defined in the ``signal`` + ``sig`` must be a valid signal number defined in the ``signal`` module. If the signal cannot be handled this raises an exception: ``ValueError`` if it is not a valid signal or if it is an uncatchable signal (e.g. ``SIGKILL``), ``RuntimeError`` if this @@ -1372,7 +1372,10 @@ the transport's ``set_write_buffer_limits()`` method. - ``resume_writing()``. Tells the protocol that it is safe to start - writing data to the transport again. Note that this may be cal + writing data to the transport again. Note that this may be called + directly by the transport's ``write()`` method (as opposed to being + called indirectly using ``call_soon()``), so that the protocol may + be aware of its paused state immediately after ``write()`` returns. - ``connection_lost(exc)``. The transport has been closed or aborted, has detected that the other end has closed the connection cleanly, @@ -1423,7 +1426,7 @@ Subprocess Protocol ''''''''''''''''''' -Subprocess protocols have ``connection_made()``, ``connection_lost()`` +Subprocess protocols have ``connection_made()``, ``connection_lost()``, ``pause_writing()`` and ``resume_writing()`` methods with the same signatures as stream protocols. In addition, they have the following methods: @@ -1635,9 +1638,9 @@ Cancelling a task that's not done yet throws an ``asyncio.CancelledError`` exception into the coroutine. If the coroutine doesn't catch this (or if it re-raises it) the task will be -marked as cancelled (i.e., ``cancelled()`` will return ``True``; but +marked as cancelled (i.e., ``cancelled()`` will return ``True``); but if the coroutine somehow catches and ignores the exception it may -continue to execute (and ``cancelled()`` will return ``False``. +continue to execute (and ``cancelled()`` will return ``False``). Tasks are also useful for interoperating between coroutines and callback-based frameworks like Twisted. After converting a coroutine @@ -1713,7 +1716,7 @@ internal buffer. This unblocks a blocked reading coroutine if it provides sufficient data to fulfill the reader's contract. - - ``feed_eof()``: Signal the end of the buffer. This unclocks a + - ``feed_eof()``: Signal the end of the buffer. This unblocks a blocked reading coroutine. No more data should be fed to the reader after this call. @@ -1766,7 +1769,7 @@ ``asyncio.queues`` submodule. In general these have a close correspondence to their threaded -counterparts, however, blocking methods (e.g. ``aqcuire()`` on locks, +counterparts, however, blocking methods (e.g. ``acquire()`` on locks, ``put()`` and ``get()`` on queues) are coroutines, and timeout parameters are not provided (you can use ``asyncio.wait_for()`` to add a timeout to a blocking call, however). @@ -1809,13 +1812,13 @@ The following classes and exceptions are provided by ``asyncio.queues``. - ``Queue``: a standard queue, with methods ``get()``, ``put()`` (both - coroutines), ``get_nowait()``, ''put_nowait()'', ``empty()``, + coroutines), ``get_nowait()``, ``put_nowait()``, ``empty()``, ``full()``, ``qsize()``, and ``maxsize()``. - ``PriorityQueue``: a subclass of ``Queue`` that retrieves entries in priority order (lowest first). -- ``LifoQueue``: a aubclass of ``Queue`` that retrieves the most +- ``LifoQueue``: a subclass of ``Queue`` that retrieves the most recently added entries first. - ``JoinableQueue``: a subclass of ``Queue`` with ``task_done()`` and @@ -1897,7 +1900,7 @@ zero and sometimes named constants (whose value is also zero)? - Do we need another inquiry method to tell whether the loop is in the - process of stopping?) + process of stopping? - A fuller public API for Handle? What's the use case? -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Feb 24 23:24:43 2014 From: python-checkins at python.org (r.david.murray) Date: Mon, 24 Feb 2014 23:24:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_http=2Eserver_?= =?utf-8?q?--bind_cli_option=2E?= Message-ID: <3fXyWH4MkGz7LkD@mail.python.org> http://hg.python.org/cpython/rev/1cc737ee45bb changeset: 89383:1cc737ee45bb user: R David Murray date: Mon Feb 24 17:21:42 2014 -0500 summary: whatsnew: http.server --bind cli option. Also some fixups in the docs. files: Doc/library/http.server.rst | 14 ++++++++------ Doc/whatsnew/3.4.rst | 4 ++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -351,7 +351,7 @@ The :class:`SimpleHTTPRequestHandler` class can be used in the following manner in order to create a very basic webserver serving files relative to -the current directory. :: +the current directory:: import http.server import socketserver @@ -365,15 +365,17 @@ print("serving at port", PORT) httpd.serve_forever() +.. _http-server-cli: + :mod:`http.server` can also be invoked directly using the :option:`-m` switch of the interpreter with a ``port number`` argument. Similar to -the previous example, this serves files relative to the current directory. :: +the previous example, this serves files relative to the current directory:: python -m http.server 8000 -By default, server binds itself to all interfaces. To restrict it to bind to a -particular interface only, ``--bind ADDRESS`` argument can be used. For e.g, to -restrict the server to bind only to localhost. :: +By default, server binds itself to all interfaces. The option ``-b/--bind`` +specifies a specific address to which it should bind. For example, the +following command causes the server to bind to localhost only:: python -m http.server 8000 --bind 127.0.0.1 @@ -422,7 +424,7 @@ reasons. Problems with the CGI script will be translated to error 403. :class:`CGIHTTPRequestHandler` can be enabled in the command line by passing -the ``--cgi`` option.:: +the ``--cgi`` option:: python -m http.server --cgi 8000 diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -801,6 +801,10 @@ :attr:`~http.server.HTTP.error_message_format` attribute and sent as the body of the error response. (Contributed by Karl Cow in :issue:`12921`.) +The :mod:`http.server` :ref:`command line interface ` now has +a ``-b/--bind`` option that causes the server to listen on a specific address. +(Contributed by Malte Swart in :issue:`17764`.) + importlib --------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Feb 24 23:31:34 2014 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 24 Feb 2014 23:31:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Clarify_that_flow_control_?= =?utf-8?q?works_for_datagrams=2C_except_on_BSD=2E?= Message-ID: <3fXygB5Kntz7LkD@mail.python.org> http://hg.python.org/cpython/rev/2072deff3b2f changeset: 89384:2072deff3b2f user: Guido van Rossum date: Mon Feb 24 14:31:25 2014 -0800 summary: Clarify that flow control works for datagrams, except on BSD. files: Doc/library/asyncio-protocol.rst | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -376,8 +376,8 @@ Flow control callbacks ---------------------- -These callbacks may be called on :class:`Protocol` and -:class:`SubprocessProtocol` instances: +These callbacks may be called on :class:`Protocol`, +:class:`DatagramProtocol` and :class:`SubprocessProtocol` instances: .. method:: BaseProtocol.pause_writing() @@ -402,6 +402,15 @@ are important to ensure that things go as expected when either mark is zero. +.. note:: + On BSD systems (OS X, FreeBSD, etc.) flow control is not supported + for :class:`DatagramProtocol`, because send failures caused by + writing too many packets cannot be detected easily. The socket + always appears 'ready' and excess packets are dropped; an + :class:`OSError` with errno set to :const:`errno.ENOBUFS` may or + may not be raised; if it is raised, it will be reported to + :meth:`DatagramProtocol.error_received` but otherwise ignored. + Coroutines and protocols ------------------------ -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Tue Feb 25 09:55:49 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 25 Feb 2014 09:55:49 +0100 Subject: [Python-checkins] Daily reference leaks (2072deff3b2f): sum=0 Message-ID: results for 2072deff3b2f on branch "default" -------------------------------------------- test_asyncio leaked [4, 0, 0] memory blocks, sum=4 test_site leaked [0, -2, 0] references, sum=-2 test_site leaked [0, -2, 0] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogi4IdMj', '-x'] From python-checkins at python.org Tue Feb 25 16:23:31 2014 From: python-checkins at python.org (r.david.murray) Date: Tue, 25 Feb 2014 16:23:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_Request=2Emeth?= =?utf-8?q?od_can_be_overridden_in_subclasses_=28=2318978=29=2E?= Message-ID: <3fYP6q3MX1z7Lm3@mail.python.org> http://hg.python.org/cpython/rev/1afbd851d1c1 changeset: 89385:1afbd851d1c1 user: R David Murray date: Tue Feb 25 10:22:50 2014 -0500 summary: whatsnew: Request.method can be overridden in subclasses (#18978). Jason doced the change in the constructor *method* description, but not the description of Request.method, so I added the change there as well. files: Doc/library/urllib.request.rst | 17 ++++++++++++----- Doc/whatsnew/3.4.rst | 5 +++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -218,7 +218,7 @@ fetching of the image, this should be true. *method* should be a string that indicates the HTTP request method that - will be used (e.g. ``'HEAD'``). Its value is stored in the + will be used (e.g. ``'HEAD'``). If provided, its value is stored in the :attr:`~Request.method` attribute and is used by :meth:`get_method()`. Subclasses may indicate a default method by setting the :attr:`~Request.method` attribute in the class itself. @@ -440,13 +440,20 @@ .. attribute:: Request.method - The HTTP request method to use. This value is used by - :meth:`~Request.get_method` to override the computed HTTP request - method that would otherwise be returned. This attribute is initialized with - the value of the *method* argument passed to the constructor. + The HTTP request method to use. By default its value is :const:`None`, + which means that :meth:`~Request.get_method` will do its normal computation + of the method to be used. Its value can be set (thus overriding the default + computation in :meth:`~Request.get_method`) either by providing a default + value by setting it at the class level in a :class:`Request` subclass, or by + passing a value in to the :class:`Request` constructor via the *method* + argument. .. versionadded:: 3.3 + .. versionchanged:: 3.4 + A default value can now be set in subclasses; previously it could only + be set via the constructor argument. + .. method:: Request.get_method() diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1272,6 +1272,11 @@ :class:`~urllib.request.DataHandler` class. (Contributed by Mathias Panzenb?ck in :issue:`16423`.) +The http method that will be used by a :class:`~urllib.request.Request` class +can now be specified by setting a :class:`~urllib.request.Request.method` +class attribute on the subclass. (Contributed by Jason R Coombs in +:issue:`18978`.) + unittest -------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 25 16:55:53 2014 From: python-checkins at python.org (r.david.murray) Date: Tue, 25 Feb 2014 16:55:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_logging_Socket?= =?utf-8?q?Handler_and_DatagramHandler_support_Unix_domain_sockets=2E?= Message-ID: <3fYPr968Rgz7Lkx@mail.python.org> http://hg.python.org/cpython/rev/85d11d71f7e6 changeset: 89386:85d11d71f7e6 user: R David Murray date: Tue Feb 25 10:39:56 2014 -0500 summary: whatsnew: logging SocketHandler and DatagramHandler support Unix domain sockets. files: Doc/whatsnew/3.4.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -897,6 +897,11 @@ parameter that can be used to specify the time of day when rollover should happen. (Contributed by Ronald Oussoren in :issue:`9556`.) +:class:`~logging.handlers.SocketHandler` and +:class:`~logging.handlers.DatagramHandler` now support Unix domain sockets (by +setting *port* to ``None``). (Contributed by Vinay Sajip in commit +ce46195b56a9.) + .. _whatsnew-marshal-3: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 25 16:55:55 2014 From: python-checkins at python.org (r.david.murray) Date: Tue, 25 Feb 2014 16:55:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_encoding_is_no?= =?utf-8?q?w_optional_in_PYTHONIOENCODING_=28=2318818=29?= Message-ID: <3fYPrC1Yvvz7Llf@mail.python.org> http://hg.python.org/cpython/rev/8ac9c3754d33 changeset: 89387:8ac9c3754d33 user: R David Murray date: Tue Feb 25 10:55:29 2014 -0500 summary: whatsnew: encoding is now optional in PYTHONIOENCODING (#18818) files: Doc/whatsnew/3.4.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1578,6 +1578,11 @@ to use copies rather than symlinks even on systems where symlinks are the default. (Contributed by Vinay Sajip in :issue:`18807`.) +* The encoding name is now optional in the value set for the + :envvar:`PYTHONIOENCODING` environment variable. This makes it possible to + set just the error handler, without changing the default encoding. + (Contributed by Serhiy Storchaka in :issue:`18818`.) + Significant Optimizations ------------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 25 19:03:14 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 25 Feb 2014 19:03:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogRml4IHR5cG8gKGlz?= =?utf-8?b?c3VlICMxOTYxOSku?= Message-ID: <3fYSg61Bwtz7LjN@mail.python.org> http://hg.python.org/cpython/rev/9975f827eefd changeset: 89388:9975f827eefd branch: 3.3 parent: 89375:9f036047187b user: Serhiy Storchaka date: Tue Feb 25 20:00:48 2014 +0200 summary: Fix typo (issue #19619). files: Include/codecs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Include/codecs.h b/Include/codecs.h --- a/Include/codecs.h +++ b/Include/codecs.h @@ -94,7 +94,7 @@ const char *errors ); -#ifndef PY_LIMITED_API +#ifndef Py_LIMITED_API /* Text codec specific encoding and decoding API. Checks the encoding against a list of codecs which do not -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 25 19:03:15 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 25 Feb 2014 19:03:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <3fYSg72Vpmz7Llt@mail.python.org> http://hg.python.org/cpython/rev/0c273c258571 changeset: 89389:0c273c258571 parent: 89387:8ac9c3754d33 parent: 89388:9975f827eefd user: Serhiy Storchaka date: Tue Feb 25 20:02:05 2014 +0200 summary: Null merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 25 20:33:09 2014 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 25 Feb 2014 20:33:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320765=3A_Add_miss?= =?utf-8?q?ing_documentation_for_PurePath=2Ewith=5Fname=28=29_and?= Message-ID: <3fYVfs6z7xzSDC@mail.python.org> http://hg.python.org/cpython/rev/879861161b84 changeset: 89390:879861161b84 user: Antoine Pitrou date: Tue Feb 25 20:33:02 2014 +0100 summary: Issue #20765: Add missing documentation for PurePath.with_name() and PurePath.with_suffix(). files: Doc/library/pathlib.rst | 30 +++++++++++++++++++++++++++++ Misc/NEWS | 6 +++++ 2 files changed, 36 insertions(+), 0 deletions(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -522,6 +522,36 @@ ValueError: '/etc/passwd' does not start with '/usr' +.. method:: PurePath.with_name(name) + + Return a new path with the :attr:`name` changed. If the original path + doesn't have a name, ValueError is raised:: + + >>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz') + >>> p.with_name('setup.py') + PureWindowsPath('c:/Downloads/setup.py') + >>> p = PureWindowsPath('c:/') + >>> p.with_name('setup.py') + Traceback (most recent call last): + File "", line 1, in + File "/home/antoine/cpython/default/Lib/pathlib.py", line 751, in with_name + raise ValueError("%r has an empty name" % (self,)) + ValueError: PureWindowsPath('c:/') has an empty name + + +.. method:: PurePath.with_suffix(suffix) + + Return a new path with the :attr:`suffix` changed. If the original path + doesn't have a suffix, the new *suffix* is appended instead:: + + >>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz') + >>> p.with_suffix('.bz2') + PureWindowsPath('c:/Downloads/pathlib.tar.bz2') + >>> p = PureWindowsPath('README') + >>> p.with_suffix('.txt') + PureWindowsPath('README.txt') + + .. _concrete-paths: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,12 @@ - Issue #19748: On AIX, time.mktime() now raises an OverflowError for year outsize range [1902; 2037]. +Documentation +------------- + +- Issue #20765: Add missing documentation for PurePath.with_name() and + PurePath.with_suffix(). + Tests ----- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 25 22:03:44 2014 From: python-checkins at python.org (r.david.murray) Date: Tue, 25 Feb 2014 22:03:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_formatting_in_NEWS_ent?= =?utf-8?b?cnku?= Message-ID: <3fYXgN3yKzz7LpS@mail.python.org> http://hg.python.org/cpython/rev/489150765b58 changeset: 89391:489150765b58 user: R David Murray date: Tue Feb 25 14:36:20 2014 -0500 summary: Fix formatting in NEWS entry. files: Misc/NEWS | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1476,9 +1476,8 @@ - Issue #19551: PEP 453 - the OS X installer now installs pip by default. -- Update third-party libraries for OS X installers: - xz 5.0.3 -> 5.0.5 - SQLite 3.7.13 -> 3.8.1 +- Update third-party libraries for OS X installers: xz 5.0.3 -> 5.0.5, + SQLite 3.7.13 -> 3.8.1 - Issue #15663: Revert OS X installer built-in Tcl/Tk support for 3.4.0b1. Some third-party projects, such as Matplotlib and PIL/Pillow, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Feb 25 22:03:45 2014 From: python-checkins at python.org (r.david.murray) Date: Tue, 25 Feb 2014 22:03:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_DynanicClassAt?= =?utf-8?q?tribute_=28=2319030=29=2C_Py=5FSetStandardStreamEncoding_=28=23?= =?utf-8?q?16129=29?= Message-ID: <3fYXgP6KZQz7LpV@mail.python.org> http://hg.python.org/cpython/rev/4cd620d8c3f6 changeset: 89392:4cd620d8c3f6 user: R David Murray date: Tue Feb 25 16:03:14 2014 -0500 summary: whatsnew: DynanicClassAttribute (#19030), Py_SetStandardStreamEncoding (#16129) Adding missing docs for DynamicClassAttribute by copying the docstring. The doc entry could stand some expansion, which I will note on the issue. files: Doc/library/types.rst | 21 +++++++++++++++++++++ Doc/whatsnew/3.4.rst | 17 +++++++++++++++++ 2 files changed, 38 insertions(+), 0 deletions(-) diff --git a/Doc/library/types.rst b/Doc/library/types.rst --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -15,6 +15,9 @@ Python interpreter, but not exposed as builtins like :class:`int` or :class:`str` are. +Finally, it provides some additional type-related utility classes and functions +that are not fundamental enough to be builtins. + Dynamic Type Creation --------------------- @@ -220,6 +223,9 @@ Return a new view of the underlying mapping's values. +Additional Utility Classes and Functions +---------------------------------------- + .. class:: SimpleNamespace A simple :class:`object` subclass that provides attribute access to its @@ -246,3 +252,18 @@ instead. .. versionadded:: 3.3 + + +.. function:: DynamicClassAttribute(fget=None, fset=None, fdel=None, doc=None) + + Route attribute access on a class to __getattr__. + + This is a descriptor, used to define attributes that act differently when + accessed through an instance and through a class. Instance access remains + normal, but access to an attribute through a class will be routed to the + class's __getattr__ method; this is done by raising AttributeError. + + This allows one to have properties active on an instance, and have virtual + attributes on the class with the same name (see Enum for an example). + + .. versionadded:: 3.4 diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1270,6 +1270,17 @@ :issue:`1565525`). +types +----- + +A new :func:`~types.DynamicClassAttribute` descriptor provides a way to define +an attribute that acts normally when looked up through an instance object, but +which is routed to the *class* ``__getattr__`` when looked up through the +class. This allows one to have properties active on a class, and have virtual +attributes on the class with the same name (see :mod:`Enum` for an example). +(Contributed by Ethan Furman in :issue:`19030`.) + + urllib ------ @@ -1512,6 +1523,12 @@ object allocator have been silenced. (Contributed by Dhiru Kholia in :issue:`18596`.) +* New function :c:func:`Py_SetStandardStreamEncoding` allows an application + that is embedding Python to do the equivalent of setting + :envvar:`PYTHONIOENCODING`. Its arguments override the equivalent + values from :envvar:`PYTHONIOENCODING` if it exists. (Contributed + by Bastien Montagne and Nick Coghlan in :issue:`16129`.) + .. _other-improvements-3.4: -- Repository URL: http://hg.python.org/cpython From ncoghlan at gmail.com Tue Feb 25 22:58:06 2014 From: ncoghlan at gmail.com (Nick Coghlan) Date: Wed, 26 Feb 2014 07:58:06 +1000 Subject: [Python-checkins] cpython: whatsnew: DynanicClassAttribute (#19030), Py_SetStandardStreamEncoding (#16129) In-Reply-To: <3fYXgP6KZQz7LpV@mail.python.org> References: <3fYXgP6KZQz7LpV@mail.python.org> Message-ID: On 26 Feb 2014 07:04, "r.david.murray" wrote: > > http://hg.python.org/cpython/rev/4cd620d8c3f6 > changeset: 89392:4cd620d8c3f6 > user: R David Murray > date: Tue Feb 25 16:03:14 2014 -0500 > summary: > whatsnew: DynanicClassAttribute (#19030), Py_SetStandardStreamEncoding (#16129) > > Adding missing docs for DynamicClassAttribute by copying the docstring. The > doc entry could stand some expansion, which I will note on the issue. > > files: > Doc/library/types.rst | 21 +++++++++++++++++++++ > Doc/whatsnew/3.4.rst | 17 +++++++++++++++++ > 2 files changed, 38 insertions(+), 0 deletions(-) > > > diff --git a/Doc/library/types.rst b/Doc/library/types.rst > --- a/Doc/library/types.rst > +++ b/Doc/library/types.rst > @@ -15,6 +15,9 @@ > Python interpreter, but not exposed as builtins like :class:`int` or > :class:`str` are. > > +Finally, it provides some additional type-related utility classes and functions > +that are not fundamental enough to be builtins. > + > > Dynamic Type Creation > --------------------- > @@ -220,6 +223,9 @@ > Return a new view of the underlying mapping's values. > > > +Additional Utility Classes and Functions > +---------------------------------------- > + > .. class:: SimpleNamespace > > A simple :class:`object` subclass that provides attribute access to its > @@ -246,3 +252,18 @@ > instead. > > .. versionadded:: 3.3 > + > + > +.. function:: DynamicClassAttribute(fget=None, fset=None, fdel=None, doc=None) > + > + Route attribute access on a class to __getattr__. > + > + This is a descriptor, used to define attributes that act differently when > + accessed through an instance and through a class. Instance access remains > + normal, but access to an attribute through a class will be routed to the > + class's __getattr__ method; this is done by raising AttributeError. > + > + This allows one to have properties active on an instance, and have virtual > + attributes on the class with the same name (see Enum for an example). > + > + .. versionadded:: 3.4 > diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst > --- a/Doc/whatsnew/3.4.rst > +++ b/Doc/whatsnew/3.4.rst > @@ -1270,6 +1270,17 @@ > :issue:`1565525`). > > > +types > +----- > + > +A new :func:`~types.DynamicClassAttribute` descriptor provides a way to define > +an attribute that acts normally when looked up through an instance object, but > +which is routed to the *class* ``__getattr__`` when looked up through the > +class. This allows one to have properties active on a class, and have virtual > +attributes on the class with the same name (see :mod:`Enum` for an example). > +(Contributed by Ethan Furman in :issue:`19030`.) > + > + > urllib > ------ > > @@ -1512,6 +1523,12 @@ > object allocator have been silenced. (Contributed by Dhiru Kholia in > :issue:`18596`.) > > +* New function :c:func:`Py_SetStandardStreamEncoding` allows an application > + that is embedding Python to do the equivalent of setting > + :envvar:`PYTHONIOENCODING`. Its arguments override the equivalent > + values from :envvar:`PYTHONIOENCODING` if it exists. (Contributed > + by Bastien Montagne and Nick Coghlan in :issue:`16129`.) > + There was an existing entry for this one: second bullet under http://docs.python.org/dev/whatsnew/3.4.html#other-build-and-c-api-changes Cheers, Nick. > > .. _other-improvements-3.4: > > > -- > Repository URL: http://hg.python.org/cpython > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > https://mail.python.org/mailman/listinfo/python-checkins > -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Wed Feb 26 01:46:57 2014 From: python-checkins at python.org (gregory.p.smith) Date: Wed, 26 Feb 2014 01:46:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Mention_issue_?= =?utf-8?q?20621_fix_in_the_NEWS_file_for_3=2E3=2E5rc1=2E?= Message-ID: <3fYdcx4ZQCz7LmZ@mail.python.org> http://hg.python.org/cpython/rev/8899e4028561 changeset: 89393:8899e4028561 branch: 3.3 parent: 89388:9975f827eefd user: Gregory P. Smith date: Tue Feb 25 16:45:55 2014 -0800 summary: Mention issue 20621 fix in the NEWS file for 3.3.5rc1. This bug was of the major reasons for the release. files: Misc/NEWS | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -26,6 +26,10 @@ Library ------- +- Issue #20621: Fixes a zipimport bug introduced in 3.3.4 that could cause + spurious crashes or SystemErrors when importing modules or packages from a + zip file. The change causing the problem was reverted. + - Issue #20635: Fixed grid_columnconfigure() and grid_rowconfigure() methods of Tkinter widgets to work in wantobjects=True mode. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 01:46:58 2014 From: python-checkins at python.org (gregory.p.smith) Date: Wed, 26 Feb 2014 01:46:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_null_merge?= Message-ID: <3fYdcy6f3Fz7LnM@mail.python.org> http://hg.python.org/cpython/rev/94edc0f0002f changeset: 89394:94edc0f0002f parent: 89392:4cd620d8c3f6 parent: 89393:8899e4028561 user: Gregory P. Smith date: Tue Feb 25 16:46:41 2014 -0800 summary: null merge files: -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Wed Feb 26 09:46:21 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 26 Feb 2014 09:46:21 +0100 Subject: [Python-checkins] Daily reference leaks (94edc0f0002f): sum=0 Message-ID: results for 94edc0f0002f on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog5Q7rb_', '-x'] From python-checkins at python.org Wed Feb 26 10:26:08 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 26 Feb 2014 10:26:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Replace_=22unit?= =?utf-8?q?test=2Emock=22_with_=22mock=22_in_unit_tests?= Message-ID: <3fYs803qmzz7LkN@mail.python.org> http://hg.python.org/cpython/rev/3a03a31a701c changeset: 89395:3a03a31a701c user: Victor Stinner date: Wed Feb 26 10:25:02 2014 +0100 summary: asyncio: Replace "unittest.mock" with "mock" in unit tests Use "from unittest import mock". It should simplify my work to merge new tests in Trollius, because Trollius uses "mock" backport for Python 2. files: Lib/asyncio/test_utils.py | 4 +- Lib/test/test_asyncio/test_base_events.py | 108 ++-- Lib/test/test_asyncio/test_events.py | 32 +- Lib/test/test_asyncio/test_futures.py | 16 +- Lib/test/test_asyncio/test_locks.py | 20 +- Lib/test/test_asyncio/test_proactor_events.py | 78 +- Lib/test/test_asyncio/test_queues.py | 4 +- Lib/test/test_asyncio/test_selector_events.py | 270 +++++----- Lib/test/test_asyncio/test_streams.py | 4 +- Lib/test/test_asyncio/test_transports.py | 6 +- Lib/test/test_asyncio/test_unix_events.py | 190 +++--- Lib/test/test_asyncio/test_windows_utils.py | 4 +- 12 files changed, 368 insertions(+), 368 deletions(-) diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -12,7 +12,7 @@ import threading import time import unittest -import unittest.mock +from unittest import mock from http.server import HTTPServer from wsgiref.simple_server import WSGIRequestHandler, WSGIServer @@ -362,7 +362,7 @@ def MockCallback(**kwargs): - return unittest.mock.Mock(spec=['__call__'], **kwargs) + return mock.Mock(spec=['__call__'], **kwargs) class MockPattern(str): diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -6,7 +6,7 @@ import sys import time import unittest -import unittest.mock +from unittest import mock from test.support import find_unused_port, IPV6_ENABLED import asyncio @@ -15,7 +15,7 @@ from asyncio import test_utils -MOCK_ANY = unittest.mock.ANY +MOCK_ANY = mock.ANY PY34 = sys.version_info >= (3, 4) @@ -23,11 +23,11 @@ def setUp(self): self.loop = base_events.BaseEventLoop() - self.loop._selector = unittest.mock.Mock() + self.loop._selector = mock.Mock() asyncio.set_event_loop(None) def test_not_implemented(self): - m = unittest.mock.Mock() + m = mock.Mock() self.assertRaises( NotImplementedError, self.loop._make_socket_transport, m, m) @@ -75,13 +75,13 @@ self.assertFalse(self.loop._ready) def test_set_default_executor(self): - executor = unittest.mock.Mock() + executor = mock.Mock() self.loop.set_default_executor(executor) self.assertIs(executor, self.loop._default_executor) def test_getnameinfo(self): - sockaddr = unittest.mock.Mock() - self.loop.run_in_executor = unittest.mock.Mock() + sockaddr = mock.Mock() + self.loop.run_in_executor = mock.Mock() self.loop.getnameinfo(sockaddr) self.assertEqual( (None, socket.getnameinfo, sockaddr, 0), @@ -111,7 +111,7 @@ def cb(arg): calls.append(arg) - self.loop._process_events = unittest.mock.Mock() + self.loop._process_events = mock.Mock() self.loop.call_later(-1, cb, 'a') self.loop.call_later(-2, cb, 'b') test_utils.run_briefly(self.loop) @@ -121,7 +121,7 @@ def cb(): self.loop.stop() - self.loop._process_events = unittest.mock.Mock() + self.loop._process_events = mock.Mock() delay = 0.1 when = self.loop.time() + delay @@ -163,7 +163,7 @@ pass h = asyncio.Handle(cb, (), self.loop) f = asyncio.Future(loop=self.loop) - executor = unittest.mock.Mock() + executor = mock.Mock() executor.submit.return_value = f self.loop.set_default_executor(executor) @@ -171,7 +171,7 @@ res = self.loop.run_in_executor(None, h) self.assertIs(f, res) - executor = unittest.mock.Mock() + executor = mock.Mock() executor.submit.return_value = f res = self.loop.run_in_executor(executor, h) self.assertIs(f, res) @@ -187,7 +187,7 @@ h1.cancel() - self.loop._process_events = unittest.mock.Mock() + self.loop._process_events = mock.Mock() self.loop._scheduled.append(h1) self.loop._scheduled.append(h2) self.loop._run_once() @@ -203,8 +203,8 @@ self.loop.set_debug(False) self.assertFalse(self.loop.get_debug()) - @unittest.mock.patch('asyncio.base_events.time') - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.time') + @mock.patch('asyncio.base_events.logger') def test__run_once_logging(self, m_logger, m_time): # Log to INFO level if timeout > 1.0 sec. idx = -1 @@ -219,7 +219,7 @@ self.loop._scheduled.append( asyncio.TimerHandle(11.0, lambda: True, (), self.loop)) - self.loop._process_events = unittest.mock.Mock() + self.loop._process_events = mock.Mock() self.loop._run_once() self.assertEqual(logging.INFO, m_logger.log.call_args[0][0]) @@ -242,7 +242,7 @@ h = asyncio.TimerHandle(time.monotonic() - 1, cb, (self.loop,), self.loop) - self.loop._process_events = unittest.mock.Mock() + self.loop._process_events = mock.Mock() self.loop._scheduled.append(h) self.loop._run_once() @@ -303,14 +303,14 @@ asyncio.SubprocessProtocol, 'exit 0', bufsize=4096) def test_default_exc_handler_callback(self): - self.loop._process_events = unittest.mock.Mock() + self.loop._process_events = mock.Mock() def zero_error(fut): fut.set_result(True) 1/0 # Test call_soon (events.Handle) - with unittest.mock.patch('asyncio.base_events.logger') as log: + with mock.patch('asyncio.base_events.logger') as log: fut = asyncio.Future(loop=self.loop) self.loop.call_soon(zero_error, fut) fut.add_done_callback(lambda fut: self.loop.stop()) @@ -320,7 +320,7 @@ exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) # Test call_later (events.TimerHandle) - with unittest.mock.patch('asyncio.base_events.logger') as log: + with mock.patch('asyncio.base_events.logger') as log: fut = asyncio.Future(loop=self.loop) self.loop.call_later(0.01, zero_error, fut) fut.add_done_callback(lambda fut: self.loop.stop()) @@ -330,7 +330,7 @@ exc_info=(ZeroDivisionError, MOCK_ANY, MOCK_ANY)) def test_default_exc_handler_coro(self): - self.loop._process_events = unittest.mock.Mock() + self.loop._process_events = mock.Mock() @asyncio.coroutine def zero_error_coro(): @@ -338,7 +338,7 @@ 1/0 # Test Future.__del__ - with unittest.mock.patch('asyncio.base_events.logger') as log: + with mock.patch('asyncio.base_events.logger') as log: fut = asyncio.async(zero_error_coro(), loop=self.loop) fut.add_done_callback(lambda *args: self.loop.stop()) self.loop.run_forever() @@ -368,9 +368,9 @@ self.loop.call_soon(zero_error) self.loop._run_once() - self.loop._process_events = unittest.mock.Mock() + self.loop._process_events = mock.Mock() - mock_handler = unittest.mock.Mock() + mock_handler = mock.Mock() self.loop.set_exception_handler(mock_handler) run_loop() mock_handler.assert_called_with(self.loop, { @@ -382,7 +382,7 @@ mock_handler.reset_mock() self.loop.set_exception_handler(None) - with unittest.mock.patch('asyncio.base_events.logger') as log: + with mock.patch('asyncio.base_events.logger') as log: run_loop() log.error.assert_called_with( test_utils.MockPattern( @@ -401,11 +401,11 @@ def handler(loop, context): raise AttributeError('spam') - self.loop._process_events = unittest.mock.Mock() + self.loop._process_events = mock.Mock() self.loop.set_exception_handler(handler) - with unittest.mock.patch('asyncio.base_events.logger') as log: + with mock.patch('asyncio.base_events.logger') as log: run_loop() log.error.assert_called_with( test_utils.MockPattern( @@ -417,8 +417,8 @@ class Loop(base_events.BaseEventLoop): - _selector = unittest.mock.Mock() - _process_events = unittest.mock.Mock() + _selector = mock.Mock() + _process_events = mock.Mock() def default_exception_handler(self, context): nonlocal _context @@ -435,7 +435,7 @@ loop.call_soon(zero_error) loop._run_once() - with unittest.mock.patch('asyncio.base_events.logger') as log: + with mock.patch('asyncio.base_events.logger') as log: run_loop() log.error.assert_called_with( 'Exception in default exception handler', @@ -446,7 +446,7 @@ _context = None loop.set_exception_handler(custom_handler) - with unittest.mock.patch('asyncio.base_events.logger') as log: + with mock.patch('asyncio.base_events.logger') as log: run_loop() log.error.assert_called_with( test_utils.MockPattern('Exception in default exception.*' @@ -527,7 +527,7 @@ def tearDown(self): self.loop.close() - @unittest.mock.patch('asyncio.base_events.socket') + @mock.patch('asyncio.base_events.socket') def test_create_connection_multiple_errors(self, m_socket): class MyProto(asyncio.Protocol): @@ -592,7 +592,7 @@ return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) self.loop.getaddrinfo = getaddrinfo_task - self.loop.sock_connect = unittest.mock.Mock() + self.loop.sock_connect = mock.Mock() self.loop.sock_connect.side_effect = OSError coro = self.loop.create_connection(MyProto, 'example.com', 80) @@ -609,7 +609,7 @@ return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) self.loop.getaddrinfo = getaddrinfo_task - self.loop.sock_connect = unittest.mock.Mock() + self.loop.sock_connect = mock.Mock() self.loop.sock_connect.side_effect = OSError coro = self.loop.create_connection( @@ -617,7 +617,7 @@ with self.assertRaises(OSError): self.loop.run_until_complete(coro) - @unittest.mock.patch('asyncio.base_events.socket') + @mock.patch('asyncio.base_events.socket') def test_create_connection_multiple_errors_local_addr(self, m_socket): def bind(addr): @@ -637,7 +637,7 @@ return asyncio.Task(getaddrinfo(*args, **kwds), loop=self.loop) self.loop.getaddrinfo = getaddrinfo_task - self.loop.sock_connect = unittest.mock.Mock() + self.loop.sock_connect = mock.Mock() self.loop.sock_connect.side_effect = OSError('Err2') coro = self.loop.create_connection( @@ -669,7 +669,7 @@ OSError, self.loop.run_until_complete, coro) def test_create_connection_ssl_server_hostname_default(self): - self.loop.getaddrinfo = unittest.mock.Mock() + self.loop.getaddrinfo = mock.Mock() def mock_getaddrinfo(*args, **kwds): f = asyncio.Future(loop=self.loop) @@ -678,9 +678,9 @@ return f self.loop.getaddrinfo.side_effect = mock_getaddrinfo - self.loop.sock_connect = unittest.mock.Mock() + self.loop.sock_connect = mock.Mock() self.loop.sock_connect.return_value = () - self.loop._make_ssl_transport = unittest.mock.Mock() + self.loop._make_ssl_transport = mock.Mock() class _SelectorTransportMock: _sock = None @@ -696,7 +696,7 @@ return transport self.loop._make_ssl_transport.side_effect = mock_make_ssl_transport - ANY = unittest.mock.ANY + ANY = mock.ANY # First try the default server_hostname. self.loop._make_ssl_transport.reset_mock() coro = self.loop.create_connection(MyProto, 'python.org', 80, ssl=True) @@ -775,13 +775,13 @@ self.assertRaises(ValueError, self.loop.run_until_complete, fut) def test_create_server_no_getaddrinfo(self): - getaddrinfo = self.loop.getaddrinfo = unittest.mock.Mock() + getaddrinfo = self.loop.getaddrinfo = mock.Mock() getaddrinfo.return_value = [] f = self.loop.create_server(MyProto, '0.0.0.0', 0) self.assertRaises(OSError, self.loop.run_until_complete, f) - @unittest.mock.patch('asyncio.base_events.socket') + @mock.patch('asyncio.base_events.socket') def test_create_server_cant_bind(self, m_socket): class Err(OSError): @@ -790,14 +790,14 @@ m_socket.getaddrinfo.return_value = [ (2, 1, 6, '', ('127.0.0.1', 10100))] m_socket.getaddrinfo._is_coroutine = False - m_sock = m_socket.socket.return_value = unittest.mock.Mock() + m_sock = m_socket.socket.return_value = mock.Mock() m_sock.bind.side_effect = Err fut = self.loop.create_server(MyProto, '0.0.0.0', 0) self.assertRaises(OSError, self.loop.run_until_complete, fut) self.assertTrue(m_sock.close.called) - @unittest.mock.patch('asyncio.base_events.socket') + @mock.patch('asyncio.base_events.socket') def test_create_datagram_endpoint_no_addrinfo(self, m_socket): m_socket.getaddrinfo.return_value = [] m_socket.getaddrinfo._is_coroutine = False @@ -818,7 +818,7 @@ AssertionError, self.loop.run_until_complete, coro) def test_create_datagram_endpoint_connect_err(self): - self.loop.sock_connect = unittest.mock.Mock() + self.loop.sock_connect = mock.Mock() self.loop.sock_connect.side_effect = OSError coro = self.loop.create_datagram_endpoint( @@ -826,7 +826,7 @@ self.assertRaises( OSError, self.loop.run_until_complete, coro) - @unittest.mock.patch('asyncio.base_events.socket') + @mock.patch('asyncio.base_events.socket') def test_create_datagram_endpoint_socket_err(self, m_socket): m_socket.getaddrinfo = socket.getaddrinfo m_socket.socket.side_effect = OSError @@ -849,7 +849,7 @@ self.assertRaises( ValueError, self.loop.run_until_complete, coro) - @unittest.mock.patch('asyncio.base_events.socket') + @mock.patch('asyncio.base_events.socket') def test_create_datagram_endpoint_setblk_err(self, m_socket): m_socket.socket.return_value.setblocking.side_effect = OSError @@ -865,14 +865,14 @@ asyncio.DatagramProtocol) self.assertRaises(ValueError, self.loop.run_until_complete, coro) - @unittest.mock.patch('asyncio.base_events.socket') + @mock.patch('asyncio.base_events.socket') def test_create_datagram_endpoint_cant_bind(self, m_socket): class Err(OSError): pass m_socket.AF_INET6 = socket.AF_INET6 m_socket.getaddrinfo = socket.getaddrinfo - m_sock = m_socket.socket.return_value = unittest.mock.Mock() + m_sock = m_socket.socket.return_value = mock.Mock() m_sock.bind.side_effect = Err fut = self.loop.create_datagram_endpoint( @@ -882,19 +882,19 @@ self.assertTrue(m_sock.close.called) def test_accept_connection_retry(self): - sock = unittest.mock.Mock() + sock = mock.Mock() sock.accept.side_effect = BlockingIOError() self.loop._accept_connection(MyProto, sock) self.assertFalse(sock.close.called) - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.logger') def test_accept_connection_exception(self, m_log): - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 sock.accept.side_effect = OSError(errno.EMFILE, 'Too many open files') - self.loop.remove_reader = unittest.mock.Mock() - self.loop.call_later = unittest.mock.Mock() + self.loop.remove_reader = mock.Mock() + self.loop.call_later = mock.Mock() self.loop._accept_connection(MyProto, sock) self.assertTrue(m_log.error.called) @@ -902,7 +902,7 @@ self.loop.remove_reader.assert_called_with(10) self.loop.call_later.assert_called_with(constants.ACCEPT_RETRY_DELAY, # self.loop._start_serving - unittest.mock.ANY, + mock.ANY, MyProto, sock, None, None) def test_call_coroutine(self): diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -20,7 +20,7 @@ import time import errno import unittest -import unittest.mock +from unittest import mock from test import support # find_unused_port, IPV6_ENABLED, TEST_HOME_DIR @@ -1812,7 +1812,7 @@ return args args = () - h = asyncio.Handle(callback, args, unittest.mock.Mock()) + h = asyncio.Handle(callback, args, mock.Mock()) self.assertIs(h._callback, callback) self.assertIs(h._args, args) self.assertFalse(h._cancelled) @@ -1844,15 +1844,15 @@ def callback(): raise ValueError() - m_loop = unittest.mock.Mock() - m_loop.call_exception_handler = unittest.mock.Mock() + m_loop = mock.Mock() + m_loop.call_exception_handler = mock.Mock() h = asyncio.Handle(callback, (), m_loop) h._run() m_loop.call_exception_handler.assert_called_with({ 'message': test_utils.MockPattern('Exception in callback.*'), - 'exception': unittest.mock.ANY, + 'exception': mock.ANY, 'handle': h }) @@ -1862,7 +1862,7 @@ def test_hash(self): when = time.monotonic() h = asyncio.TimerHandle(when, lambda: False, (), - unittest.mock.Mock()) + mock.Mock()) self.assertEqual(hash(h), hash(when)) def test_timer(self): @@ -1871,7 +1871,7 @@ args = () when = time.monotonic() - h = asyncio.TimerHandle(when, callback, args, unittest.mock.Mock()) + h = asyncio.TimerHandle(when, callback, args, mock.Mock()) self.assertIs(h._callback, callback) self.assertIs(h._args, args) self.assertFalse(h._cancelled) @@ -1887,10 +1887,10 @@ self.assertRaises(AssertionError, asyncio.TimerHandle, None, callback, args, - unittest.mock.Mock()) + mock.Mock()) def test_timer_comparison(self): - loop = unittest.mock.Mock() + loop = mock.Mock() def callback(*args): return args @@ -1935,7 +1935,7 @@ class AbstractEventLoopTests(unittest.TestCase): def test_not_implemented(self): - f = unittest.mock.Mock() + f = mock.Mock() loop = asyncio.AbstractEventLoop() self.assertRaises( NotImplementedError, loop.run_forever) @@ -1995,13 +1995,13 @@ NotImplementedError, loop.remove_signal_handler, 1) self.assertRaises( NotImplementedError, loop.connect_read_pipe, f, - unittest.mock.sentinel.pipe) + mock.sentinel.pipe) self.assertRaises( NotImplementedError, loop.connect_write_pipe, f, - unittest.mock.sentinel.pipe) + mock.sentinel.pipe) self.assertRaises( NotImplementedError, loop.subprocess_shell, f, - unittest.mock.sentinel) + mock.sentinel) self.assertRaises( NotImplementedError, loop.subprocess_exec, f) @@ -2009,7 +2009,7 @@ class ProtocolsAbsTests(unittest.TestCase): def test_empty(self): - f = unittest.mock.Mock() + f = mock.Mock() p = asyncio.Protocol() self.assertIsNone(p.connection_made(f)) self.assertIsNone(p.connection_lost(f)) @@ -2055,7 +2055,7 @@ def test_get_event_loop_calls_set_event_loop(self): policy = asyncio.DefaultEventLoopPolicy() - with unittest.mock.patch.object( + with mock.patch.object( policy, "set_event_loop", wraps=policy.set_event_loop) as m_set_event_loop: @@ -2073,7 +2073,7 @@ policy.set_event_loop(None) self.assertRaises(AssertionError, policy.get_event_loop) - @unittest.mock.patch('asyncio.events.threading.current_thread') + @mock.patch('asyncio.events.threading.current_thread') def test_get_event_loop_thread(self, m_current_thread): def f(): diff --git a/Lib/test/test_asyncio/test_futures.py b/Lib/test/test_asyncio/test_futures.py --- a/Lib/test/test_asyncio/test_futures.py +++ b/Lib/test/test_asyncio/test_futures.py @@ -3,7 +3,7 @@ import concurrent.futures import threading import unittest -import unittest.mock +from unittest import mock import asyncio from asyncio import test_utils @@ -174,20 +174,20 @@ self.assertRaises(AssertionError, test) fut.cancel() - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.logger') def test_tb_logger_abandoned(self, m_log): fut = asyncio.Future(loop=self.loop) del fut self.assertFalse(m_log.error.called) - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.logger') def test_tb_logger_result_unretrieved(self, m_log): fut = asyncio.Future(loop=self.loop) fut.set_result(42) del fut self.assertFalse(m_log.error.called) - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.logger') def test_tb_logger_result_retrieved(self, m_log): fut = asyncio.Future(loop=self.loop) fut.set_result(42) @@ -195,7 +195,7 @@ del fut self.assertFalse(m_log.error.called) - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.logger') def test_tb_logger_exception_unretrieved(self, m_log): fut = asyncio.Future(loop=self.loop) fut.set_exception(RuntimeError('boom')) @@ -203,7 +203,7 @@ test_utils.run_briefly(self.loop) self.assertTrue(m_log.error.called) - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.logger') def test_tb_logger_exception_retrieved(self, m_log): fut = asyncio.Future(loop=self.loop) fut.set_exception(RuntimeError('boom')) @@ -211,7 +211,7 @@ del fut self.assertFalse(m_log.error.called) - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.logger') def test_tb_logger_exception_result_retrieved(self, m_log): fut = asyncio.Future(loop=self.loop) fut.set_exception(RuntimeError('boom')) @@ -236,7 +236,7 @@ f2 = asyncio.wrap_future(f1) self.assertIs(f1, f2) - @unittest.mock.patch('asyncio.futures.events') + @mock.patch('asyncio.futures.events') def test_wrap_future_use_global_loop(self, m_events): def run(arg): return (arg, threading.get_ident()) diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -1,7 +1,7 @@ """Tests for lock.py""" import unittest -import unittest.mock +from unittest import mock import re import asyncio @@ -27,7 +27,7 @@ self.loop.close() def test_ctor_loop(self): - loop = unittest.mock.Mock() + loop = mock.Mock() lock = asyncio.Lock(loop=loop) self.assertIs(lock._loop, loop) @@ -250,7 +250,7 @@ self.loop.close() def test_ctor_loop(self): - loop = unittest.mock.Mock() + loop = mock.Mock() ev = asyncio.Event(loop=loop) self.assertIs(ev._loop, loop) @@ -275,7 +275,7 @@ self.assertTrue(repr(ev).endswith('[set]>')) self.assertTrue(RGX_REPR.match(repr(ev))) - ev._waiters.append(unittest.mock.Mock()) + ev._waiters.append(mock.Mock()) self.assertTrue('waiters:1' in repr(ev)) self.assertTrue(RGX_REPR.match(repr(ev))) @@ -386,7 +386,7 @@ self.loop.close() def test_ctor_loop(self): - loop = unittest.mock.Mock() + loop = mock.Mock() cond = asyncio.Condition(loop=loop) self.assertIs(cond._loop, loop) @@ -644,11 +644,11 @@ self.loop.run_until_complete(cond.acquire()) self.assertTrue('locked' in repr(cond)) - cond._waiters.append(unittest.mock.Mock()) + cond._waiters.append(mock.Mock()) self.assertTrue('waiters:1' in repr(cond)) self.assertTrue(RGX_REPR.match(repr(cond))) - cond._waiters.append(unittest.mock.Mock()) + cond._waiters.append(mock.Mock()) self.assertTrue('waiters:2' in repr(cond)) self.assertTrue(RGX_REPR.match(repr(cond))) @@ -688,7 +688,7 @@ self.loop.close() def test_ctor_loop(self): - loop = unittest.mock.Mock() + loop = mock.Mock() sem = asyncio.Semaphore(loop=loop) self.assertIs(sem._loop, loop) @@ -717,11 +717,11 @@ self.assertTrue('waiters' not in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) - sem._waiters.append(unittest.mock.Mock()) + sem._waiters.append(mock.Mock()) self.assertTrue('waiters:1' in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) - sem._waiters.append(unittest.mock.Mock()) + sem._waiters.append(mock.Mock()) self.assertTrue('waiters:2' in repr(sem)) self.assertTrue(RGX_REPR.match(repr(sem))) diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -2,7 +2,7 @@ import socket import unittest -import unittest.mock +from unittest import mock import asyncio from asyncio.proactor_events import BaseProactorEventLoop @@ -16,10 +16,10 @@ def setUp(self): self.loop = test_utils.TestLoop() - self.proactor = unittest.mock.Mock() + self.proactor = mock.Mock() self.loop._proactor = self.proactor self.protocol = test_utils.make_test_protocol(asyncio.Protocol) - self.sock = unittest.mock.Mock(socket.socket) + self.sock = mock.Mock(socket.socket) def test_ctor(self): fut = asyncio.Future(loop=self.loop) @@ -56,7 +56,7 @@ self.assertRaises(AssertionError, tr._loop_reading, res) - tr.close = unittest.mock.Mock() + tr.close = mock.Mock() tr._read_fut = res tr._loop_reading(res) self.assertFalse(self.loop._proactor.recv.called) @@ -67,7 +67,7 @@ err = self.loop._proactor.recv.side_effect = ConnectionAbortedError() tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) - tr._fatal_error = unittest.mock.Mock() + tr._fatal_error = mock.Mock() tr._loop_reading() tr._fatal_error.assert_called_with( err, @@ -78,7 +78,7 @@ tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._closing = True - tr._fatal_error = unittest.mock.Mock() + tr._fatal_error = mock.Mock() tr._loop_reading() self.assertFalse(tr._fatal_error.called) @@ -86,7 +86,7 @@ self.loop._proactor.recv.side_effect = ConnectionAbortedError() tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._closing = False - tr._fatal_error = unittest.mock.Mock() + tr._fatal_error = mock.Mock() tr._loop_reading() self.assertTrue(tr._fatal_error.called) @@ -95,8 +95,8 @@ tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._closing = False - tr._fatal_error = unittest.mock.Mock() - tr._force_close = unittest.mock.Mock() + tr._fatal_error = mock.Mock() + tr._force_close = mock.Mock() tr._loop_reading() self.assertFalse(tr._fatal_error.called) tr._force_close.assert_called_with(err) @@ -105,7 +105,7 @@ err = self.loop._proactor.recv.side_effect = (OSError()) tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) - tr._fatal_error = unittest.mock.Mock() + tr._fatal_error = mock.Mock() tr._loop_reading() tr._fatal_error.assert_called_with( err, @@ -113,7 +113,7 @@ def test_write(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) - tr._loop_writing = unittest.mock.Mock() + tr._loop_writing = mock.Mock() tr.write(b'data') self.assertEqual(tr._buffer, None) tr._loop_writing.assert_called_with(data=b'data') @@ -125,8 +125,8 @@ def test_write_more(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) - tr._write_fut = unittest.mock.Mock() - tr._loop_writing = unittest.mock.Mock() + tr._write_fut = mock.Mock() + tr._loop_writing = mock.Mock() tr.write(b'data') self.assertEqual(tr._buffer, b'data') self.assertFalse(tr._loop_writing.called) @@ -139,11 +139,11 @@ self.loop._proactor.send.return_value.add_done_callback.\ assert_called_with(tr._loop_writing) - @unittest.mock.patch('asyncio.proactor_events.logger') + @mock.patch('asyncio.proactor_events.logger') def test_loop_writing_err(self, m_log): err = self.loop._proactor.send.side_effect = OSError() tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) - tr._fatal_error = unittest.mock.Mock() + tr._fatal_error = mock.Mock() tr._buffer = [b'da', b'ta'] tr._loop_writing() tr._fatal_error.assert_called_with( @@ -182,7 +182,7 @@ def test_abort(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) - tr._force_close = unittest.mock.Mock() + tr._force_close = mock.Mock() tr.abort() tr._force_close.assert_called_with(None) @@ -201,7 +201,7 @@ def test_close_write_fut(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) - tr._write_fut = unittest.mock.Mock() + tr._write_fut = mock.Mock() tr.close() test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.connection_lost.called) @@ -213,10 +213,10 @@ test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.connection_lost.called) - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.logger') def test_fatal_error(self, m_logging): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) - tr._force_close = unittest.mock.Mock() + tr._force_close = mock.Mock() tr._fatal_error(None) self.assertTrue(tr._force_close.called) self.assertTrue(m_logging.error.called) @@ -224,8 +224,8 @@ def test_force_close(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._buffer = [b'data'] - read_fut = tr._read_fut = unittest.mock.Mock() - write_fut = tr._write_fut = unittest.mock.Mock() + read_fut = tr._read_fut = mock.Mock() + write_fut = tr._write_fut = mock.Mock() tr._force_close(None) read_fut.cancel.assert_called_with() @@ -346,10 +346,10 @@ class BaseProactorEventLoopTests(unittest.TestCase): def setUp(self): - self.sock = unittest.mock.Mock(socket.socket) - self.proactor = unittest.mock.Mock() + self.sock = mock.Mock(socket.socket) + self.proactor = mock.Mock() - self.ssock, self.csock = unittest.mock.Mock(), unittest.mock.Mock() + self.ssock, self.csock = mock.Mock(), mock.Mock() class EventLoop(BaseProactorEventLoop): def _socketpair(s): @@ -357,11 +357,11 @@ self.loop = EventLoop(self.proactor) - @unittest.mock.patch.object(BaseProactorEventLoop, 'call_soon') - @unittest.mock.patch.object(BaseProactorEventLoop, '_socketpair') + @mock.patch.object(BaseProactorEventLoop, 'call_soon') + @mock.patch.object(BaseProactorEventLoop, '_socketpair') def test_ctor(self, socketpair, call_soon): ssock, csock = socketpair.return_value = ( - unittest.mock.Mock(), unittest.mock.Mock()) + mock.Mock(), mock.Mock()) loop = BaseProactorEventLoop(self.proactor) self.assertIs(loop._ssock, ssock) self.assertIs(loop._csock, csock) @@ -377,7 +377,7 @@ self.assertIsNone(self.loop._csock) def test_close(self): - self.loop._close_self_pipe = unittest.mock.Mock() + self.loop._close_self_pipe = mock.Mock() self.loop.close() self.assertTrue(self.loop._close_self_pipe.called) self.assertTrue(self.proactor.close.called) @@ -418,7 +418,7 @@ self.loop._loop_self_reading) def test_loop_self_reading_fut(self): - fut = unittest.mock.Mock() + fut = mock.Mock() self.loop._loop_self_reading(fut) self.assertTrue(fut.result.called) self.proactor.recv.assert_called_with(self.ssock, 4096) @@ -426,7 +426,7 @@ self.loop._loop_self_reading) def test_loop_self_reading_exception(self): - self.loop.close = unittest.mock.Mock() + self.loop.close = mock.Mock() self.proactor.recv.side_effect = OSError() self.assertRaises(OSError, self.loop._loop_self_reading) self.assertTrue(self.loop.close.called) @@ -438,10 +438,10 @@ def test_process_events(self): self.loop._process_events([]) - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.logger') def test_create_server(self, m_log): - pf = unittest.mock.Mock() - call_soon = self.loop.call_soon = unittest.mock.Mock() + pf = mock.Mock() + call_soon = self.loop.call_soon = mock.Mock() self.loop._start_serving(pf, self.sock) self.assertTrue(call_soon.called) @@ -452,10 +452,10 @@ self.proactor.accept.assert_called_with(self.sock) # conn - fut = unittest.mock.Mock() - fut.result.return_value = (unittest.mock.Mock(), unittest.mock.Mock()) + fut = mock.Mock() + fut.result.return_value = (mock.Mock(), mock.Mock()) - make_tr = self.loop._make_socket_transport = unittest.mock.Mock() + make_tr = self.loop._make_socket_transport = mock.Mock() loop(fut) self.assertTrue(fut.result.called) self.assertTrue(make_tr.called) @@ -467,8 +467,8 @@ self.assertTrue(m_log.error.called) def test_create_server_cancel(self): - pf = unittest.mock.Mock() - call_soon = self.loop.call_soon = unittest.mock.Mock() + pf = mock.Mock() + call_soon = self.loop.call_soon = mock.Mock() self.loop._start_serving(pf, self.sock) loop = call_soon.call_args[0][0] @@ -480,7 +480,7 @@ self.assertTrue(self.sock.close.called) def test_stop_serving(self): - sock = unittest.mock.Mock() + sock = mock.Mock() self.loop._stop_serving(sock) self.assertTrue(sock.close.called) self.proactor._stop_serving.assert_called_with(sock) diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -1,7 +1,7 @@ """Tests for queues.py""" import unittest -import unittest.mock +from unittest import mock import asyncio from asyncio import test_utils @@ -72,7 +72,7 @@ self.assertTrue('_queue=[1]' in fn(q)) def test_ctor_loop(self): - loop = unittest.mock.Mock() + loop = mock.Mock() q = asyncio.Queue(loop=loop) self.assertIs(q._loop, loop) diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -7,7 +7,7 @@ import socket import sys import unittest -import unittest.mock +from unittest import mock try: import ssl except ImportError: @@ -23,14 +23,14 @@ from asyncio.selector_events import _SelectorDatagramTransport -MOCK_ANY = unittest.mock.ANY +MOCK_ANY = mock.ANY class TestBaseSelectorEventLoop(BaseSelectorEventLoop): def _make_self_pipe(self): - self._ssock = unittest.mock.Mock() - self._csock = unittest.mock.Mock() + self._ssock = mock.Mock() + self._csock = mock.Mock() self._internal_fds += 1 @@ -41,34 +41,34 @@ class BaseSelectorEventLoopTests(unittest.TestCase): def setUp(self): - selector = unittest.mock.Mock() + selector = mock.Mock() self.loop = TestBaseSelectorEventLoop(selector) def test_make_socket_transport(self): - m = unittest.mock.Mock() - self.loop.add_reader = unittest.mock.Mock() + m = mock.Mock() + self.loop.add_reader = mock.Mock() transport = self.loop._make_socket_transport(m, asyncio.Protocol()) self.assertIsInstance(transport, _SelectorSocketTransport) @unittest.skipIf(ssl is None, 'No ssl module') def test_make_ssl_transport(self): - m = unittest.mock.Mock() - self.loop.add_reader = unittest.mock.Mock() - self.loop.add_writer = unittest.mock.Mock() - self.loop.remove_reader = unittest.mock.Mock() - self.loop.remove_writer = unittest.mock.Mock() + m = mock.Mock() + self.loop.add_reader = mock.Mock() + self.loop.add_writer = mock.Mock() + self.loop.remove_reader = mock.Mock() + self.loop.remove_writer = mock.Mock() waiter = asyncio.Future(loop=self.loop) transport = self.loop._make_ssl_transport( m, asyncio.Protocol(), m, waiter) self.assertIsInstance(transport, _SelectorSslTransport) - @unittest.mock.patch('asyncio.selector_events.ssl', None) + @mock.patch('asyncio.selector_events.ssl', None) def test_make_ssl_transport_without_ssl_error(self): - m = unittest.mock.Mock() - self.loop.add_reader = unittest.mock.Mock() - self.loop.add_writer = unittest.mock.Mock() - self.loop.remove_reader = unittest.mock.Mock() - self.loop.remove_writer = unittest.mock.Mock() + m = mock.Mock() + self.loop.add_reader = mock.Mock() + self.loop.add_writer = mock.Mock() + self.loop.remove_reader = mock.Mock() + self.loop.remove_writer = mock.Mock() with self.assertRaises(RuntimeError): self.loop._make_ssl_transport(m, m, m, m) @@ -77,10 +77,10 @@ ssock.fileno.return_value = 7 csock = self.loop._csock csock.fileno.return_value = 1 - remove_reader = self.loop.remove_reader = unittest.mock.Mock() + remove_reader = self.loop.remove_reader = mock.Mock() self.loop._selector.close() - self.loop._selector = selector = unittest.mock.Mock() + self.loop._selector = selector = mock.Mock() self.loop.close() self.assertIsNone(self.loop._selector) self.assertIsNone(self.loop._csock) @@ -96,7 +96,7 @@ def test_close_no_selector(self): ssock = self.loop._ssock csock = self.loop._csock - remove_reader = self.loop.remove_reader = unittest.mock.Mock() + remove_reader = self.loop.remove_reader = mock.Mock() self.loop._selector.close() self.loop._selector = None @@ -126,15 +126,15 @@ self.assertRaises(OSError, self.loop._write_to_self) def test_sock_recv(self): - sock = unittest.mock.Mock() - self.loop._sock_recv = unittest.mock.Mock() + sock = mock.Mock() + 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, False, sock, 1024) def test__sock_recv_canceled_fut(self): - sock = unittest.mock.Mock() + sock = mock.Mock() f = asyncio.Future(loop=self.loop) f.cancel() @@ -143,30 +143,30 @@ self.assertFalse(sock.recv.called) def test__sock_recv_unregister(self): - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 f = asyncio.Future(loop=self.loop) f.cancel() - self.loop.remove_reader = unittest.mock.Mock() + self.loop.remove_reader = mock.Mock() self.loop._sock_recv(f, True, sock, 1024) self.assertEqual((10,), self.loop.remove_reader.call_args[0]) def test__sock_recv_tryagain(self): f = asyncio.Future(loop=self.loop) - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 sock.recv.side_effect = BlockingIOError - self.loop.add_reader = unittest.mock.Mock() + self.loop.add_reader = mock.Mock() self.loop._sock_recv(f, False, sock, 1024) self.assertEqual((10, self.loop._sock_recv, f, True, sock, 1024), self.loop.add_reader.call_args[0]) def test__sock_recv_exception(self): f = asyncio.Future(loop=self.loop) - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 err = sock.recv.side_effect = OSError() @@ -174,8 +174,8 @@ self.assertIs(err, f.exception()) def test_sock_sendall(self): - sock = unittest.mock.Mock() - self.loop._sock_sendall = unittest.mock.Mock() + sock = mock.Mock() + self.loop._sock_sendall = mock.Mock() f = self.loop.sock_sendall(sock, b'data') self.assertIsInstance(f, asyncio.Future) @@ -184,8 +184,8 @@ self.loop._sock_sendall.call_args[0]) def test_sock_sendall_nodata(self): - sock = unittest.mock.Mock() - self.loop._sock_sendall = unittest.mock.Mock() + sock = mock.Mock() + self.loop._sock_sendall = mock.Mock() f = self.loop.sock_sendall(sock, b'') self.assertIsInstance(f, asyncio.Future) @@ -194,7 +194,7 @@ self.assertFalse(self.loop._sock_sendall.called) def test__sock_sendall_canceled_fut(self): - sock = unittest.mock.Mock() + sock = mock.Mock() f = asyncio.Future(loop=self.loop) f.cancel() @@ -203,23 +203,23 @@ self.assertFalse(sock.send.called) def test__sock_sendall_unregister(self): - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 f = asyncio.Future(loop=self.loop) f.cancel() - self.loop.remove_writer = unittest.mock.Mock() + self.loop.remove_writer = mock.Mock() self.loop._sock_sendall(f, True, sock, b'data') self.assertEqual((10,), self.loop.remove_writer.call_args[0]) def test__sock_sendall_tryagain(self): f = asyncio.Future(loop=self.loop) - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 sock.send.side_effect = BlockingIOError - self.loop.add_writer = unittest.mock.Mock() + self.loop.add_writer = mock.Mock() self.loop._sock_sendall(f, False, sock, b'data') self.assertEqual( (10, self.loop._sock_sendall, f, True, sock, b'data'), @@ -227,11 +227,11 @@ def test__sock_sendall_interrupted(self): f = asyncio.Future(loop=self.loop) - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 sock.send.side_effect = InterruptedError - self.loop.add_writer = unittest.mock.Mock() + self.loop.add_writer = mock.Mock() self.loop._sock_sendall(f, False, sock, b'data') self.assertEqual( (10, self.loop._sock_sendall, f, True, sock, b'data'), @@ -239,7 +239,7 @@ def test__sock_sendall_exception(self): f = asyncio.Future(loop=self.loop) - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 err = sock.send.side_effect = OSError() @@ -247,7 +247,7 @@ self.assertIs(f.exception(), err) def test__sock_sendall(self): - sock = unittest.mock.Mock() + sock = mock.Mock() f = asyncio.Future(loop=self.loop) sock.fileno.return_value = 10 @@ -258,13 +258,13 @@ self.assertIsNone(f.result()) def test__sock_sendall_partial(self): - sock = unittest.mock.Mock() + sock = mock.Mock() f = asyncio.Future(loop=self.loop) sock.fileno.return_value = 10 sock.send.return_value = 2 - self.loop.add_writer = unittest.mock.Mock() + self.loop.add_writer = mock.Mock() self.loop._sock_sendall(f, False, sock, b'data') self.assertFalse(f.done()) self.assertEqual( @@ -272,13 +272,13 @@ self.loop.add_writer.call_args[0]) def test__sock_sendall_none(self): - sock = unittest.mock.Mock() + sock = mock.Mock() f = asyncio.Future(loop=self.loop) sock.fileno.return_value = 10 sock.send.return_value = 0 - self.loop.add_writer = unittest.mock.Mock() + self.loop.add_writer = mock.Mock() self.loop._sock_sendall(f, False, sock, b'data') self.assertFalse(f.done()) self.assertEqual( @@ -286,8 +286,8 @@ self.loop.add_writer.call_args[0]) def test_sock_connect(self): - sock = unittest.mock.Mock() - self.loop._sock_connect = unittest.mock.Mock() + sock = mock.Mock() + self.loop._sock_connect = mock.Mock() f = self.loop.sock_connect(sock, ('127.0.0.1', 8080)) self.assertIsInstance(f, asyncio.Future) @@ -298,7 +298,7 @@ def test__sock_connect(self): f = asyncio.Future(loop=self.loop) - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 self.loop._sock_connect(f, False, sock, ('127.0.0.1', 8080)) @@ -307,7 +307,7 @@ self.assertTrue(sock.connect.called) def test__sock_connect_canceled_fut(self): - sock = unittest.mock.Mock() + sock = mock.Mock() f = asyncio.Future(loop=self.loop) f.cancel() @@ -316,24 +316,24 @@ self.assertFalse(sock.connect.called) def test__sock_connect_unregister(self): - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 f = asyncio.Future(loop=self.loop) f.cancel() - self.loop.remove_writer = unittest.mock.Mock() + self.loop.remove_writer = mock.Mock() self.loop._sock_connect(f, True, sock, ('127.0.0.1', 8080)) self.assertEqual((10,), self.loop.remove_writer.call_args[0]) def test__sock_connect_tryagain(self): f = asyncio.Future(loop=self.loop) - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 sock.getsockopt.return_value = errno.EAGAIN - self.loop.add_writer = unittest.mock.Mock() - self.loop.remove_writer = unittest.mock.Mock() + self.loop.add_writer = mock.Mock() + self.loop.remove_writer = mock.Mock() self.loop._sock_connect(f, True, sock, ('127.0.0.1', 8080)) self.assertEqual( @@ -343,17 +343,17 @@ def test__sock_connect_exception(self): f = asyncio.Future(loop=self.loop) - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 sock.getsockopt.return_value = errno.ENOTCONN - self.loop.remove_writer = unittest.mock.Mock() + self.loop.remove_writer = mock.Mock() self.loop._sock_connect(f, True, sock, ('127.0.0.1', 8080)) self.assertIsInstance(f.exception(), OSError) def test_sock_accept(self): - sock = unittest.mock.Mock() - self.loop._sock_accept = unittest.mock.Mock() + sock = mock.Mock() + self.loop._sock_accept = mock.Mock() f = self.loop.sock_accept(sock) self.assertIsInstance(f, asyncio.Future) @@ -363,9 +363,9 @@ def test__sock_accept(self): f = asyncio.Future(loop=self.loop) - conn = unittest.mock.Mock() + conn = mock.Mock() - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 sock.accept.return_value = conn, ('127.0.0.1', 1000) @@ -375,7 +375,7 @@ self.assertEqual((False,), conn.setblocking.call_args[0]) def test__sock_accept_canceled_fut(self): - sock = unittest.mock.Mock() + sock = mock.Mock() f = asyncio.Future(loop=self.loop) f.cancel() @@ -384,23 +384,23 @@ self.assertFalse(sock.accept.called) def test__sock_accept_unregister(self): - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 f = asyncio.Future(loop=self.loop) f.cancel() - self.loop.remove_reader = unittest.mock.Mock() + self.loop.remove_reader = mock.Mock() self.loop._sock_accept(f, True, sock) self.assertEqual((10,), self.loop.remove_reader.call_args[0]) def test__sock_accept_tryagain(self): f = asyncio.Future(loop=self.loop) - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 sock.accept.side_effect = BlockingIOError - self.loop.add_reader = unittest.mock.Mock() + self.loop.add_reader = mock.Mock() self.loop._sock_accept(f, False, sock) self.assertEqual( (10, self.loop._sock_accept, f, True, sock), @@ -408,7 +408,7 @@ def test__sock_accept_exception(self): f = asyncio.Future(loop=self.loop) - sock = unittest.mock.Mock() + sock = mock.Mock() sock.fileno.return_value = 10 err = sock.accept.side_effect = OSError() @@ -428,8 +428,8 @@ self.assertIsNone(w) def test_add_reader_existing(self): - reader = unittest.mock.Mock() - writer = unittest.mock.Mock() + reader = mock.Mock() + writer = mock.Mock() self.loop._selector.get_key.return_value = selectors.SelectorKey( 1, 1, selectors.EVENT_WRITE, (reader, writer)) cb = lambda: True @@ -445,7 +445,7 @@ self.assertEqual(writer, w) def test_add_reader_existing_writer(self): - writer = unittest.mock.Mock() + writer = mock.Mock() self.loop._selector.get_key.return_value = selectors.SelectorKey( 1, 1, selectors.EVENT_WRITE, (None, writer)) cb = lambda: True @@ -467,8 +467,8 @@ self.assertTrue(self.loop._selector.unregister.called) def test_remove_reader_read_write(self): - reader = unittest.mock.Mock() - writer = unittest.mock.Mock() + reader = mock.Mock() + writer = mock.Mock() self.loop._selector.get_key.return_value = selectors.SelectorKey( 1, 1, selectors.EVENT_READ | selectors.EVENT_WRITE, (reader, writer)) @@ -498,8 +498,8 @@ self.assertEqual(cb, w._callback) def test_add_writer_existing(self): - reader = unittest.mock.Mock() - writer = unittest.mock.Mock() + reader = mock.Mock() + writer = mock.Mock() self.loop._selector.get_key.return_value = selectors.SelectorKey( 1, 1, selectors.EVENT_READ, (reader, writer)) cb = lambda: True @@ -522,8 +522,8 @@ self.assertTrue(self.loop._selector.unregister.called) def test_remove_writer_read_write(self): - reader = unittest.mock.Mock() - writer = unittest.mock.Mock() + reader = mock.Mock() + writer = mock.Mock() self.loop._selector.get_key.return_value = selectors.SelectorKey( 1, 1, selectors.EVENT_READ | selectors.EVENT_WRITE, (reader, writer)) @@ -541,10 +541,10 @@ self.loop.remove_writer(1)) def test_process_events_read(self): - reader = unittest.mock.Mock() + reader = mock.Mock() reader._cancelled = False - self.loop._add_callback = unittest.mock.Mock() + self.loop._add_callback = mock.Mock() self.loop._process_events( [(selectors.SelectorKey( 1, 1, selectors.EVENT_READ, (reader, None)), @@ -553,10 +553,10 @@ self.loop._add_callback.assert_called_with(reader) def test_process_events_read_cancelled(self): - reader = unittest.mock.Mock() + reader = mock.Mock() reader.cancelled = True - self.loop.remove_reader = unittest.mock.Mock() + self.loop.remove_reader = mock.Mock() self.loop._process_events( [(selectors.SelectorKey( 1, 1, selectors.EVENT_READ, (reader, None)), @@ -564,10 +564,10 @@ self.loop.remove_reader.assert_called_with(1) def test_process_events_write(self): - writer = unittest.mock.Mock() + writer = mock.Mock() writer._cancelled = False - self.loop._add_callback = unittest.mock.Mock() + self.loop._add_callback = mock.Mock() self.loop._process_events( [(selectors.SelectorKey(1, 1, selectors.EVENT_WRITE, (None, writer)), @@ -575,9 +575,9 @@ self.loop._add_callback.assert_called_with(writer) def test_process_events_write_cancelled(self): - writer = unittest.mock.Mock() + writer = mock.Mock() writer.cancelled = True - self.loop.remove_writer = unittest.mock.Mock() + self.loop.remove_writer = mock.Mock() self.loop._process_events( [(selectors.SelectorKey(1, 1, selectors.EVENT_WRITE, @@ -591,7 +591,7 @@ def setUp(self): self.loop = test_utils.TestLoop() self.protocol = test_utils.make_test_protocol(asyncio.Protocol) - self.sock = unittest.mock.Mock(socket.socket) + self.sock = mock.Mock(socket.socket) self.sock.fileno.return_value = 7 def test_ctor(self): @@ -602,7 +602,7 @@ def test_abort(self): tr = _SelectorTransport(self.loop, self.sock, self.protocol, None) - tr._force_close = unittest.mock.Mock() + tr._force_close = mock.Mock() tr.abort() tr._force_close.assert_called_with(None) @@ -632,8 +632,8 @@ def test_force_close(self): tr = _SelectorTransport(self.loop, self.sock, self.protocol, None) tr._buffer.extend(b'1') - self.loop.add_reader(7, unittest.mock.sentinel) - self.loop.add_writer(7, unittest.mock.sentinel) + self.loop.add_reader(7, mock.sentinel) + self.loop.add_writer(7, mock.sentinel) tr._force_close(None) self.assertTrue(tr._closing) @@ -646,11 +646,11 @@ self.assertFalse(self.loop.readers) self.assertEqual(1, self.loop.remove_reader_count[7]) - @unittest.mock.patch('asyncio.log.logger.error') + @mock.patch('asyncio.log.logger.error') def test_fatal_error(self, m_exc): exc = OSError() tr = _SelectorTransport(self.loop, self.sock, self.protocol, None) - tr._force_close = unittest.mock.Mock() + tr._force_close = mock.Mock() tr._fatal_error(exc) m_exc.assert_called_with( @@ -682,7 +682,7 @@ def setUp(self): self.loop = test_utils.TestLoop() self.protocol = test_utils.make_test_protocol(asyncio.Protocol) - self.sock = unittest.mock.Mock(socket.socket) + self.sock = mock.Mock(socket.socket) self.sock_fd = self.sock.fileno.return_value = 7 def test_ctor(self): @@ -724,7 +724,7 @@ def test_read_ready_eof(self): transport = _SelectorSocketTransport( self.loop, self.sock, self.protocol) - transport.close = unittest.mock.Mock() + transport.close = mock.Mock() self.sock.recv.return_value = b'' transport._read_ready() @@ -735,7 +735,7 @@ def test_read_ready_eof_keep_open(self): transport = _SelectorSocketTransport( self.loop, self.sock, self.protocol) - transport.close = unittest.mock.Mock() + transport.close = mock.Mock() self.sock.recv.return_value = b'' self.protocol.eof_received.return_value = True @@ -744,45 +744,45 @@ self.protocol.eof_received.assert_called_with() self.assertFalse(transport.close.called) - @unittest.mock.patch('logging.exception') + @mock.patch('logging.exception') def test_read_ready_tryagain(self, m_exc): self.sock.recv.side_effect = BlockingIOError transport = _SelectorSocketTransport( self.loop, self.sock, self.protocol) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._read_ready() self.assertFalse(transport._fatal_error.called) - @unittest.mock.patch('logging.exception') + @mock.patch('logging.exception') def test_read_ready_tryagain_interrupted(self, m_exc): self.sock.recv.side_effect = InterruptedError transport = _SelectorSocketTransport( self.loop, self.sock, self.protocol) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._read_ready() self.assertFalse(transport._fatal_error.called) - @unittest.mock.patch('logging.exception') + @mock.patch('logging.exception') def test_read_ready_conn_reset(self, m_exc): err = self.sock.recv.side_effect = ConnectionResetError() transport = _SelectorSocketTransport( self.loop, self.sock, self.protocol) - transport._force_close = unittest.mock.Mock() + transport._force_close = mock.Mock() transport._read_ready() transport._force_close.assert_called_with(err) - @unittest.mock.patch('logging.exception') + @mock.patch('logging.exception') def test_read_ready_err(self, m_exc): err = self.sock.recv.side_effect = OSError() transport = _SelectorSocketTransport( self.loop, self.sock, self.protocol) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._read_ready() transport._fatal_error.assert_called_with( @@ -891,14 +891,14 @@ self.loop.assert_writer(7, transport._write_ready) self.assertEqual(list_to_buffer([b'data']), transport._buffer) - @unittest.mock.patch('asyncio.selector_events.logger') + @mock.patch('asyncio.selector_events.logger') def test_write_exception(self, m_log): err = self.sock.send.side_effect = OSError() data = b'data' transport = _SelectorSocketTransport( self.loop, self.sock, self.protocol) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport.write(data) transport._fatal_error.assert_called_with( err, @@ -1002,17 +1002,17 @@ transport = _SelectorSocketTransport( self.loop, self.sock, self.protocol) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._buffer.extend(b'data') transport._write_ready() transport._fatal_error.assert_called_with( err, 'Fatal write error on socket transport') - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.base_events.logger') def test_write_ready_exception_and_close(self, m_log): self.sock.send.side_effect = OSError() - remove_writer = self.loop.remove_writer = unittest.mock.Mock() + remove_writer = self.loop.remove_writer = mock.Mock() transport = _SelectorSocketTransport( self.loop, self.sock, self.protocol) @@ -1053,11 +1053,11 @@ def setUp(self): self.loop = test_utils.TestLoop() self.protocol = test_utils.make_test_protocol(asyncio.Protocol) - self.sock = unittest.mock.Mock(socket.socket) + self.sock = mock.Mock(socket.socket) self.sock.fileno.return_value = 7 - self.sslsock = unittest.mock.Mock() + self.sslsock = mock.Mock() self.sslsock.fileno.return_value = 1 - self.sslcontext = unittest.mock.Mock() + self.sslcontext = mock.Mock() self.sslcontext.wrap_socket.return_value = self.sslsock def _make_one(self, create_waiter=None): @@ -1162,7 +1162,7 @@ transport.write(b'data') self.assertEqual(transport._conn_lost, 2) - @unittest.mock.patch('asyncio.selector_events.logger') + @mock.patch('asyncio.selector_events.logger') def test_write_exception(self, m_log): transport = self._make_one() transport._conn_lost = 1 @@ -1182,11 +1182,11 @@ self.assertEqual((b'data',), self.protocol.data_received.call_args[0]) def test_read_ready_write_wants_read(self): - self.loop.add_writer = unittest.mock.Mock() + self.loop.add_writer = mock.Mock() self.sslsock.recv.side_effect = BlockingIOError transport = self._make_one() transport._write_wants_read = True - transport._write_ready = unittest.mock.Mock() + transport._write_ready = mock.Mock() transport._buffer.extend(b'data') transport._read_ready() @@ -1198,7 +1198,7 @@ def test_read_ready_recv_eof(self): self.sslsock.recv.return_value = b'' transport = self._make_one() - transport.close = unittest.mock.Mock() + transport.close = mock.Mock() transport._read_ready() transport.close.assert_called_with() self.protocol.eof_received.assert_called_with() @@ -1206,7 +1206,7 @@ def test_read_ready_recv_conn_reset(self): err = self.sslsock.recv.side_effect = ConnectionResetError() transport = self._make_one() - transport._force_close = unittest.mock.Mock() + transport._force_close = mock.Mock() transport._read_ready() transport._force_close.assert_called_with(err) @@ -1226,8 +1226,8 @@ self.assertFalse(self.protocol.data_received.called) def test_read_ready_recv_write(self): - self.loop.remove_reader = unittest.mock.Mock() - self.loop.add_writer = unittest.mock.Mock() + self.loop.remove_reader = mock.Mock() + self.loop.add_writer = mock.Mock() self.sslsock.recv.side_effect = ssl.SSLWantWriteError transport = self._make_one() transport._read_ready() @@ -1241,7 +1241,7 @@ def test_read_ready_recv_exc(self): err = self.sslsock.recv.side_effect = OSError() transport = self._make_one() - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._read_ready() transport._fatal_error.assert_called_with( err, @@ -1313,7 +1313,7 @@ transport = self._make_one() transport._buffer = list_to_buffer([b'data']) - self.loop.remove_writer = unittest.mock.Mock() + self.loop.remove_writer = mock.Mock() self.sslsock.send.side_effect = ssl.SSLWantReadError transport._write_ready() self.assertFalse(self.protocol.data_received.called) @@ -1325,7 +1325,7 @@ transport = self._make_one() transport._buffer = list_to_buffer([b'data']) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._write_ready() transport._fatal_error.assert_called_with( err, @@ -1333,11 +1333,11 @@ self.assertEqual(list_to_buffer(), transport._buffer) def test_write_ready_read_wants_write(self): - self.loop.add_reader = unittest.mock.Mock() + self.loop.add_reader = mock.Mock() self.sslsock.send.side_effect = BlockingIOError transport = self._make_one() transport._read_wants_write = True - transport._read_ready = unittest.mock.Mock() + transport._read_ready = mock.Mock() transport._write_ready() self.assertFalse(transport._read_wants_write) @@ -1374,9 +1374,9 @@ class SelectorSslWithoutSslTransportTests(unittest.TestCase): - @unittest.mock.patch('asyncio.selector_events.ssl', None) + @mock.patch('asyncio.selector_events.ssl', None) def test_ssl_transport_requires_ssl_module(self): - Mock = unittest.mock.Mock + Mock = mock.Mock with self.assertRaises(RuntimeError): transport = _SelectorSslTransport(Mock(), Mock(), Mock(), Mock()) @@ -1386,7 +1386,7 @@ def setUp(self): self.loop = test_utils.TestLoop() self.protocol = test_utils.make_test_protocol(asyncio.DatagramProtocol) - self.sock = unittest.mock.Mock(spec_set=socket.socket) + self.sock = mock.Mock(spec_set=socket.socket) self.sock.fileno.return_value = 7 def test_read_ready(self): @@ -1404,7 +1404,7 @@ self.loop, self.sock, self.protocol) self.sock.recvfrom.side_effect = BlockingIOError - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._read_ready() self.assertFalse(transport._fatal_error.called) @@ -1414,7 +1414,7 @@ self.loop, self.sock, self.protocol) err = self.sock.recvfrom.side_effect = RuntimeError() - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._read_ready() transport._fatal_error.assert_called_with( @@ -1426,7 +1426,7 @@ self.loop, self.sock, self.protocol) err = self.sock.recvfrom.side_effect = OSError() - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._read_ready() self.assertFalse(transport._fatal_error.called) @@ -1518,14 +1518,14 @@ self.assertEqual( [(b'data', ('0.0.0.0', 12345))], list(transport._buffer)) - @unittest.mock.patch('asyncio.selector_events.logger') + @mock.patch('asyncio.selector_events.logger') def test_sendto_exception(self, m_log): data = b'data' err = self.sock.sendto.side_effect = RuntimeError() transport = _SelectorDatagramTransport( self.loop, self.sock, self.protocol) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport.sendto(data, ()) self.assertTrue(transport._fatal_error.called) @@ -1549,7 +1549,7 @@ transport = _SelectorDatagramTransport( self.loop, self.sock, self.protocol) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport.sendto(data, ()) self.assertEqual(transport._conn_lost, 0) @@ -1562,7 +1562,7 @@ transport = _SelectorDatagramTransport( self.loop, self.sock, self.protocol, ('0.0.0.0', 1)) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport.sendto(data) self.assertFalse(transport._fatal_error.called) @@ -1643,7 +1643,7 @@ transport = _SelectorDatagramTransport( self.loop, self.sock, self.protocol) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._buffer.append((b'data', ())) transport._sendto_ready() @@ -1656,7 +1656,7 @@ transport = _SelectorDatagramTransport( self.loop, self.sock, self.protocol) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._buffer.append((b'data', ())) transport._sendto_ready() @@ -1667,14 +1667,14 @@ transport = _SelectorDatagramTransport( self.loop, self.sock, self.protocol, ('0.0.0.0', 1)) - transport._fatal_error = unittest.mock.Mock() + transport._fatal_error = mock.Mock() transport._buffer.append((b'data', ())) transport._sendto_ready() self.assertFalse(transport._fatal_error.called) self.assertTrue(self.protocol.error_received.called) - @unittest.mock.patch('asyncio.base_events.logger.error') + @mock.patch('asyncio.base_events.logger.error') def test_fatal_error_connected(self, m_exc): transport = _SelectorDatagramTransport( self.loop, self.sock, self.protocol, ('0.0.0.0', 1)) diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -4,7 +4,7 @@ import gc import socket import unittest -import unittest.mock +from unittest import mock try: import ssl except ImportError: @@ -29,7 +29,7 @@ self.loop.close() gc.collect() - @unittest.mock.patch('asyncio.streams.events') + @mock.patch('asyncio.streams.events') def test_ctor_global_loop(self, m_events): stream = asyncio.StreamReader() self.assertIs(stream._loop, m_events.get_event_loop.return_value) diff --git a/Lib/test/test_asyncio/test_transports.py b/Lib/test/test_asyncio/test_transports.py --- a/Lib/test/test_asyncio/test_transports.py +++ b/Lib/test/test_asyncio/test_transports.py @@ -1,7 +1,7 @@ """Tests for transports.py.""" import unittest -import unittest.mock +from unittest import mock import asyncio from asyncio import transports @@ -23,7 +23,7 @@ def test_writelines(self): transport = asyncio.Transport() - transport.write = unittest.mock.Mock() + transport.write = mock.Mock() transport.writelines([b'line1', bytearray(b'line2'), @@ -70,7 +70,7 @@ return 512 transport = MyTransport() - transport._protocol = unittest.mock.Mock() + transport._protocol = mock.Mock() self.assertFalse(transport._protocol_paused) diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -13,7 +13,7 @@ import tempfile import threading import unittest -import unittest.mock +from unittest import mock if sys.platform == 'win32': raise unittest.SkipTest('UNIX only') @@ -25,7 +25,7 @@ from asyncio import unix_events -MOCK_ANY = unittest.mock.ANY +MOCK_ANY = mock.ANY @unittest.skipUnless(signal, 'Signals are not supported') @@ -48,15 +48,15 @@ self.loop._handle_signal(signal.NSIG + 1, ()) def test_handle_signal_cancelled_handler(self): - h = asyncio.Handle(unittest.mock.Mock(), (), - loop=unittest.mock.Mock()) + h = asyncio.Handle(mock.Mock(), (), + loop=mock.Mock()) h.cancel() self.loop._signal_handlers[signal.NSIG + 1] = h - self.loop.remove_signal_handler = unittest.mock.Mock() + self.loop.remove_signal_handler = mock.Mock() self.loop._handle_signal(signal.NSIG + 1, ()) self.loop.remove_signal_handler.assert_called_with(signal.NSIG + 1) - @unittest.mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.unix_events.signal') def test_add_signal_handler_setup_error(self, m_signal): m_signal.NSIG = signal.NSIG m_signal.set_wakeup_fd.side_effect = ValueError @@ -66,7 +66,7 @@ self.loop.add_signal_handler, signal.SIGINT, lambda: True) - @unittest.mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.unix_events.signal') def test_add_signal_handler(self, m_signal): m_signal.NSIG = signal.NSIG @@ -76,7 +76,7 @@ self.assertIsInstance(h, asyncio.Handle) self.assertEqual(h._callback, cb) - @unittest.mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.unix_events.signal') def test_add_signal_handler_install_error(self, m_signal): m_signal.NSIG = signal.NSIG @@ -94,8 +94,8 @@ self.loop.add_signal_handler, signal.SIGINT, lambda: True) - @unittest.mock.patch('asyncio.unix_events.signal') - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.base_events.logger') def test_add_signal_handler_install_error2(self, m_logging, m_signal): m_signal.NSIG = signal.NSIG @@ -111,8 +111,8 @@ self.assertFalse(m_logging.info.called) self.assertEqual(1, m_signal.set_wakeup_fd.call_count) - @unittest.mock.patch('asyncio.unix_events.signal') - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.base_events.logger') def test_add_signal_handler_install_error3(self, m_logging, m_signal): class Err(OSError): errno = errno.EINVAL @@ -126,7 +126,7 @@ self.assertFalse(m_logging.info.called) self.assertEqual(2, m_signal.set_wakeup_fd.call_count) - @unittest.mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.unix_events.signal') def test_remove_signal_handler(self, m_signal): m_signal.NSIG = signal.NSIG @@ -139,7 +139,7 @@ self.assertEqual( (signal.SIGHUP, m_signal.SIG_DFL), m_signal.signal.call_args[0]) - @unittest.mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.unix_events.signal') def test_remove_signal_handler_2(self, m_signal): m_signal.NSIG = signal.NSIG m_signal.SIGINT = signal.SIGINT @@ -156,8 +156,8 @@ (signal.SIGINT, m_signal.default_int_handler), m_signal.signal.call_args[0]) - @unittest.mock.patch('asyncio.unix_events.signal') - @unittest.mock.patch('asyncio.base_events.logger') + @mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.base_events.logger') def test_remove_signal_handler_cleanup_error(self, m_logging, m_signal): m_signal.NSIG = signal.NSIG self.loop.add_signal_handler(signal.SIGHUP, lambda: True) @@ -167,7 +167,7 @@ self.loop.remove_signal_handler(signal.SIGHUP) self.assertTrue(m_logging.info) - @unittest.mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.unix_events.signal') def test_remove_signal_handler_error(self, m_signal): m_signal.NSIG = signal.NSIG self.loop.add_signal_handler(signal.SIGHUP, lambda: True) @@ -177,7 +177,7 @@ self.assertRaises( OSError, self.loop.remove_signal_handler, signal.SIGHUP) - @unittest.mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.unix_events.signal') def test_remove_signal_handler_error2(self, m_signal): m_signal.NSIG = signal.NSIG self.loop.add_signal_handler(signal.SIGHUP, lambda: True) @@ -189,7 +189,7 @@ self.assertRaises( RuntimeError, self.loop.remove_signal_handler, signal.SIGHUP) - @unittest.mock.patch('asyncio.unix_events.signal') + @mock.patch('asyncio.unix_events.signal') def test_close(self, m_signal): m_signal.NSIG = signal.NSIG @@ -291,16 +291,16 @@ def setUp(self): self.loop = test_utils.TestLoop() self.protocol = test_utils.make_test_protocol(asyncio.Protocol) - self.pipe = unittest.mock.Mock(spec_set=io.RawIOBase) + self.pipe = mock.Mock(spec_set=io.RawIOBase) self.pipe.fileno.return_value = 5 - fcntl_patcher = unittest.mock.patch('fcntl.fcntl') + fcntl_patcher = mock.patch('fcntl.fcntl') fcntl_patcher.start() self.addCleanup(fcntl_patcher.stop) - fstat_patcher = unittest.mock.patch('os.fstat') + fstat_patcher = mock.patch('os.fstat') m_fstat = fstat_patcher.start() - st = unittest.mock.Mock() + st = mock.Mock() st.st_mode = stat.S_IFIFO m_fstat.return_value = st self.addCleanup(fstat_patcher.stop) @@ -319,7 +319,7 @@ test_utils.run_briefly(self.loop) self.assertIsNone(fut.result()) - @unittest.mock.patch('os.read') + @mock.patch('os.read') def test__read_ready(self, m_read): tr = unix_events._UnixReadPipeTransport( self.loop, self.pipe, self.protocol) @@ -329,7 +329,7 @@ m_read.assert_called_with(5, tr.max_size) self.protocol.data_received.assert_called_with(b'data') - @unittest.mock.patch('os.read') + @mock.patch('os.read') def test__read_ready_eof(self, m_read): tr = unix_events._UnixReadPipeTransport( self.loop, self.pipe, self.protocol) @@ -342,7 +342,7 @@ self.protocol.eof_received.assert_called_with() self.protocol.connection_lost.assert_called_with(None) - @unittest.mock.patch('os.read') + @mock.patch('os.read') def test__read_ready_blocked(self, m_read): tr = unix_events._UnixReadPipeTransport( self.loop, self.pipe, self.protocol) @@ -353,14 +353,14 @@ test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.data_received.called) - @unittest.mock.patch('asyncio.log.logger.error') - @unittest.mock.patch('os.read') + @mock.patch('asyncio.log.logger.error') + @mock.patch('os.read') def test__read_ready_error(self, m_read, m_logexc): tr = unix_events._UnixReadPipeTransport( self.loop, self.pipe, self.protocol) err = OSError() m_read.side_effect = err - tr._close = unittest.mock.Mock() + tr._close = mock.Mock() tr._read_ready() m_read.assert_called_with(5, tr.max_size) @@ -371,17 +371,17 @@ '\nprotocol:.*\ntransport:.*'), exc_info=(OSError, MOCK_ANY, MOCK_ANY)) - @unittest.mock.patch('os.read') + @mock.patch('os.read') def test_pause_reading(self, m_read): tr = unix_events._UnixReadPipeTransport( self.loop, self.pipe, self.protocol) - m = unittest.mock.Mock() + m = mock.Mock() self.loop.add_reader(5, m) tr.pause_reading() self.assertFalse(self.loop.readers) - @unittest.mock.patch('os.read') + @mock.patch('os.read') def test_resume_reading(self, m_read): tr = unix_events._UnixReadPipeTransport( self.loop, self.pipe, self.protocol) @@ -389,26 +389,26 @@ tr.resume_reading() self.loop.assert_reader(5, tr._read_ready) - @unittest.mock.patch('os.read') + @mock.patch('os.read') def test_close(self, m_read): tr = unix_events._UnixReadPipeTransport( self.loop, self.pipe, self.protocol) - tr._close = unittest.mock.Mock() + tr._close = mock.Mock() tr.close() tr._close.assert_called_with(None) - @unittest.mock.patch('os.read') + @mock.patch('os.read') def test_close_already_closing(self, m_read): tr = unix_events._UnixReadPipeTransport( self.loop, self.pipe, self.protocol) tr._closing = True - tr._close = unittest.mock.Mock() + tr._close = mock.Mock() tr.close() self.assertFalse(tr._close.called) - @unittest.mock.patch('os.read') + @mock.patch('os.read') def test__close(self, m_read): tr = unix_events._UnixReadPipeTransport( self.loop, self.pipe, self.protocol) @@ -459,16 +459,16 @@ def setUp(self): self.loop = test_utils.TestLoop() self.protocol = test_utils.make_test_protocol(asyncio.BaseProtocol) - self.pipe = unittest.mock.Mock(spec_set=io.RawIOBase) + self.pipe = mock.Mock(spec_set=io.RawIOBase) self.pipe.fileno.return_value = 5 - fcntl_patcher = unittest.mock.patch('fcntl.fcntl') + fcntl_patcher = mock.patch('fcntl.fcntl') fcntl_patcher.start() self.addCleanup(fcntl_patcher.stop) - fstat_patcher = unittest.mock.patch('os.fstat') + fstat_patcher = mock.patch('os.fstat') m_fstat = fstat_patcher.start() - st = unittest.mock.Mock() + st = mock.Mock() st.st_mode = stat.S_IFSOCK m_fstat.return_value = st self.addCleanup(fstat_patcher.stop) @@ -493,7 +493,7 @@ self.loop, self.pipe, self.protocol) self.assertTrue(tr.can_write_eof()) - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test_write(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -504,7 +504,7 @@ self.assertFalse(self.loop.writers) self.assertEqual([], tr._buffer) - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test_write_no_data(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -514,7 +514,7 @@ self.assertFalse(self.loop.writers) self.assertEqual([], tr._buffer) - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test_write_partial(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -525,7 +525,7 @@ self.loop.assert_writer(5, tr._write_ready) self.assertEqual([b'ta'], tr._buffer) - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test_write_buffer(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -537,7 +537,7 @@ self.loop.assert_writer(5, tr._write_ready) self.assertEqual([b'previous', b'data'], tr._buffer) - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test_write_again(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -548,15 +548,15 @@ self.loop.assert_writer(5, tr._write_ready) self.assertEqual([b'data'], tr._buffer) - @unittest.mock.patch('asyncio.unix_events.logger') - @unittest.mock.patch('os.write') + @mock.patch('asyncio.unix_events.logger') + @mock.patch('os.write') def test_write_err(self, m_write, m_log): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) err = OSError() m_write.side_effect = err - tr._fatal_error = unittest.mock.Mock() + tr._fatal_error = mock.Mock() tr.write(b'data') m_write.assert_called_with(5, b'data') self.assertFalse(self.loop.writers) @@ -576,7 +576,7 @@ m_log.warning.assert_called_with( 'pipe closed by peer or os.write(pipe, data) raised exception.') - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test_write_close(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -597,7 +597,7 @@ test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(None) - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test__write_ready(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -609,7 +609,7 @@ self.assertFalse(self.loop.writers) self.assertEqual([], tr._buffer) - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test__write_ready_partial(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -622,7 +622,7 @@ self.loop.assert_writer(5, tr._write_ready) self.assertEqual([b'a'], tr._buffer) - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test__write_ready_again(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -635,7 +635,7 @@ self.loop.assert_writer(5, tr._write_ready) self.assertEqual([b'data'], tr._buffer) - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test__write_ready_empty(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -648,8 +648,8 @@ self.loop.assert_writer(5, tr._write_ready) self.assertEqual([b'data'], tr._buffer) - @unittest.mock.patch('asyncio.log.logger.error') - @unittest.mock.patch('os.write') + @mock.patch('asyncio.log.logger.error') + @mock.patch('os.write') def test__write_ready_err(self, m_write, m_logexc): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -672,7 +672,7 @@ test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(err) - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test__write_ready_closing(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -689,7 +689,7 @@ self.protocol.connection_lost.assert_called_with(None) self.pipe.close.assert_called_with() - @unittest.mock.patch('os.write') + @mock.patch('os.write') def test_abort(self, m_write): tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) @@ -742,7 +742,7 @@ tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) - tr.write_eof = unittest.mock.Mock() + tr.write_eof = mock.Mock() tr.close() tr.write_eof.assert_called_with() @@ -750,7 +750,7 @@ tr = unix_events._UnixWritePipeTransport( self.loop, self.pipe, self.protocol) - tr.write_eof = unittest.mock.Mock() + tr.write_eof = mock.Mock() tr._closing = True tr.close() self.assertFalse(tr.write_eof.called) @@ -777,7 +777,7 @@ class AbstractChildWatcherTests(unittest.TestCase): def test_not_implemented(self): - f = unittest.mock.Mock() + f = mock.Mock() watcher = asyncio.AbstractChildWatcher() self.assertRaises( NotImplementedError, watcher.add_child_handler, f, f) @@ -796,7 +796,7 @@ class BaseChildWatcherTests(unittest.TestCase): def test_not_implemented(self): - f = unittest.mock.Mock() + f = mock.Mock() watcher = unix_events.BaseChildWatcher() self.assertRaises( NotImplementedError, watcher._do_waitpid, f) @@ -813,14 +813,14 @@ class ChildWatcherTestsMixin: - ignore_warnings = unittest.mock.patch.object(log.logger, "warning") + ignore_warnings = mock.patch.object(log.logger, "warning") def setUp(self): self.loop = test_utils.TestLoop() self.running = False self.zombies = {} - with unittest.mock.patch.object( + with mock.patch.object( self.loop, "add_signal_handler") as self.m_add_signal_handler: self.watcher = self.create_watcher() self.watcher.attach_loop(self.loop) @@ -864,8 +864,8 @@ def waitpid_mocks(func): def wrapped_func(self): def patch(target, wrapper): - return unittest.mock.patch(target, wraps=wrapper, - new_callable=unittest.mock.Mock) + return mock.patch(target, wraps=wrapper, + new_callable=mock.Mock) with patch('os.WTERMSIG', self.WTERMSIG) as m_WTERMSIG, \ patch('os.WEXITSTATUS', self.WEXITSTATUS) as m_WEXITSTATUS, \ @@ -881,7 +881,7 @@ @waitpid_mocks def test_sigchld(self, m): # register a child - callback = unittest.mock.Mock() + callback = mock.Mock() with self.watcher: self.running = True @@ -941,8 +941,8 @@ @waitpid_mocks def test_sigchld_two_children(self, m): - callback1 = unittest.mock.Mock() - callback2 = unittest.mock.Mock() + callback1 = mock.Mock() + callback2 = mock.Mock() # register child 1 with self.watcher: @@ -1045,8 +1045,8 @@ @waitpid_mocks def test_sigchld_two_children_terminating_together(self, m): - callback1 = unittest.mock.Mock() - callback2 = unittest.mock.Mock() + callback1 = mock.Mock() + callback2 = mock.Mock() # register child 1 with self.watcher: @@ -1115,7 +1115,7 @@ @waitpid_mocks def test_sigchld_race_condition(self, m): # register a child - callback = unittest.mock.Mock() + callback = mock.Mock() with self.watcher: # child terminates before being registered @@ -1136,8 +1136,8 @@ @waitpid_mocks def test_sigchld_replace_handler(self, m): - callback1 = unittest.mock.Mock() - callback2 = unittest.mock.Mock() + callback1 = mock.Mock() + callback2 = mock.Mock() # register a child with self.watcher: @@ -1189,7 +1189,7 @@ @waitpid_mocks def test_sigchld_remove_handler(self, m): - callback = unittest.mock.Mock() + callback = mock.Mock() # register a child with self.watcher: @@ -1221,7 +1221,7 @@ @waitpid_mocks def test_sigchld_unknown_status(self, m): - callback = unittest.mock.Mock() + callback = mock.Mock() # register a child with self.watcher: @@ -1258,9 +1258,9 @@ @waitpid_mocks def test_remove_child_handler(self, m): - callback1 = unittest.mock.Mock() - callback2 = unittest.mock.Mock() - callback3 = unittest.mock.Mock() + callback1 = mock.Mock() + callback2 = mock.Mock() + callback3 = mock.Mock() # register children with self.watcher: @@ -1291,7 +1291,7 @@ @waitpid_mocks def test_sigchld_unhandled_exception(self, m): - callback = unittest.mock.Mock() + callback = mock.Mock() # register a child with self.watcher: @@ -1301,7 +1301,7 @@ # raise an exception m.waitpid.side_effect = ValueError - with unittest.mock.patch.object(log.logger, + with mock.patch.object(log.logger, 'error') as m_error: self.assertEqual(self.watcher._sig_chld(), None) @@ -1310,7 +1310,7 @@ @waitpid_mocks def test_sigchld_child_reaped_elsewhere(self, m): # register a child - callback = unittest.mock.Mock() + callback = mock.Mock() with self.watcher: self.running = True @@ -1346,8 +1346,8 @@ @waitpid_mocks def test_sigchld_unknown_pid_during_registration(self, m): # register two children - callback1 = unittest.mock.Mock() - callback2 = unittest.mock.Mock() + callback1 = mock.Mock() + callback2 = mock.Mock() with self.ignore_warnings, self.watcher: self.running = True @@ -1367,7 +1367,7 @@ @waitpid_mocks def test_set_loop(self, m): # register a child - callback = unittest.mock.Mock() + callback = mock.Mock() with self.watcher: self.running = True @@ -1377,10 +1377,10 @@ old_loop = self.loop self.loop = test_utils.TestLoop() - with unittest.mock.patch.object( + with mock.patch.object( old_loop, "remove_signal_handler") as m_old_remove_signal_handler, \ - unittest.mock.patch.object( + mock.patch.object( self.loop, "add_signal_handler") as m_new_add_signal_handler: @@ -1401,9 +1401,9 @@ @waitpid_mocks def test_set_loop_race_condition(self, m): # register 3 children - callback1 = unittest.mock.Mock() - callback2 = unittest.mock.Mock() - callback3 = unittest.mock.Mock() + callback1 = mock.Mock() + callback2 = mock.Mock() + callback3 = mock.Mock() with self.watcher: self.running = True @@ -1415,7 +1415,7 @@ old_loop = self.loop self.loop = None - with unittest.mock.patch.object( + with mock.patch.object( old_loop, "remove_signal_handler") as m_remove_signal_handler: self.watcher.attach_loop(None) @@ -1435,7 +1435,7 @@ # attach a new loop self.loop = test_utils.TestLoop() - with unittest.mock.patch.object( + with mock.patch.object( self.loop, "add_signal_handler") as m_add_signal_handler: self.watcher.attach_loop(self.loop) @@ -1461,8 +1461,8 @@ @waitpid_mocks def test_close(self, m): # register two children - callback1 = unittest.mock.Mock() - callback2 = unittest.mock.Mock() + callback1 = mock.Mock() + callback2 = mock.Mock() with self.watcher: self.running = True @@ -1479,7 +1479,7 @@ if isinstance(self.watcher, asyncio.FastChildWatcher): self.assertEqual(len(self.watcher._zombies), 1) - with unittest.mock.patch.object( + with mock.patch.object( self.loop, "remove_signal_handler") as m_remove_signal_handler: diff --git a/Lib/test/test_asyncio/test_windows_utils.py b/Lib/test/test_asyncio/test_windows_utils.py --- a/Lib/test/test_asyncio/test_windows_utils.py +++ b/Lib/test/test_asyncio/test_windows_utils.py @@ -3,7 +3,7 @@ import sys import test.support import unittest -import unittest.mock +from unittest import mock if sys.platform != 'win32': raise unittest.SkipTest('Windows only') @@ -25,7 +25,7 @@ csock.close() ssock.close() - @unittest.mock.patch('asyncio.windows_utils.socket') + @mock.patch('asyncio.windows_utils.socket') def test_winsocketpair_exc(self, m_socket): m_socket.socket.return_value.getsockname.return_value = ('', 12345) m_socket.socket.return_value.accept.return_value = object(), object() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 11:07:59 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 26 Feb 2014 11:07:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_Fix_pyflakes_wa?= =?utf-8?q?rnings=3A_remove_unused_variables_and_imports?= Message-ID: <3fYt4H3cDFz7Ljf@mail.python.org> http://hg.python.org/cpython/rev/99991b782bb4 changeset: 89396:99991b782bb4 user: Victor Stinner date: Wed Feb 26 11:07:42 2014 +0100 summary: asyncio: Fix pyflakes warnings: remove unused variables and imports files: Lib/asyncio/test_utils.py | 1 - Lib/test/test_asyncio/test_base_events.py | 2 +- Lib/test/test_asyncio/test_events.py | 4 +- Lib/test/test_asyncio/test_selector_events.py | 3 +- Lib/test/test_asyncio/test_streams.py | 1 - Lib/test/test_asyncio/test_tasks.py | 8 +--- Lib/test/test_asyncio/test_unix_events.py | 16 +++------ Lib/test/test_asyncio/test_windows_events.py | 3 +- 8 files changed, 12 insertions(+), 26 deletions(-) diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py --- a/Lib/asyncio/test_utils.py +++ b/Lib/asyncio/test_utils.py @@ -11,7 +11,6 @@ import tempfile import threading import time -import unittest from unittest import mock from http.server import HTTPServer diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -7,7 +7,7 @@ import time import unittest from unittest import mock -from test.support import find_unused_port, IPV6_ENABLED +from test.support import IPV6_ENABLED import asyncio from asyncio import base_events diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -25,7 +25,6 @@ import asyncio -from asyncio import events from asyncio import selector_events from asyncio import test_utils @@ -1648,13 +1647,12 @@ def test_subprocess_wait_no_same_group(self): proto = None - transp = None @asyncio.coroutine def connect(): nonlocal proto # start the new process in a new session - transp, proto = yield from self.loop.subprocess_shell( + _, proto = yield from self.loop.subprocess_shell( functools.partial(MySubprocessProtocol, self.loop), 'exit 7', stdin=None, stdout=None, stderr=None, start_new_session=True) diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -1,6 +1,5 @@ """Tests for selector_events.py""" -import collections import errno import gc import pprint @@ -1378,7 +1377,7 @@ def test_ssl_transport_requires_ssl_module(self): Mock = mock.Mock with self.assertRaises(RuntimeError): - transport = _SelectorSslTransport(Mock(), Mock(), Mock(), Mock()) + _SelectorSslTransport(Mock(), Mock(), Mock(), Mock()) class SelectorDatagramTransportTests(unittest.TestCase): diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -1,6 +1,5 @@ """Tests for streams.py.""" -import functools import gc import socket import unittest diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -830,7 +830,7 @@ v = yield from f self.assertEqual(v, 'a') - res = loop.run_until_complete(asyncio.Task(foo(), loop=loop)) + loop.run_until_complete(asyncio.Task(foo(), loop=loop)) def test_as_completed_reverse_wait(self): @@ -964,13 +964,9 @@ loop = test_utils.TestLoop(gen) self.addCleanup(loop.close) - sleepfut = None - @asyncio.coroutine def sleep(dt): - nonlocal sleepfut - sleepfut = asyncio.sleep(dt, loop=loop) - yield from sleepfut + yield from asyncio.sleep(dt, loop=loop) @asyncio.coroutine def doit(): diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -1302,7 +1302,7 @@ m.waitpid.side_effect = ValueError with mock.patch.object(log.logger, - 'error') as m_error: + 'error') as m_error: self.assertEqual(self.watcher._sig_chld(), None) self.assertTrue(m_error.called) @@ -1376,19 +1376,16 @@ # attach a new loop old_loop = self.loop self.loop = test_utils.TestLoop() + patch = mock.patch.object - with mock.patch.object( - old_loop, - "remove_signal_handler") as m_old_remove_signal_handler, \ - mock.patch.object( - self.loop, - "add_signal_handler") as m_new_add_signal_handler: + with patch(old_loop, "remove_signal_handler") as m_old_remove, \ + patch(self.loop, "add_signal_handler") as m_new_add: self.watcher.attach_loop(self.loop) - m_old_remove_signal_handler.assert_called_once_with( + m_old_remove.assert_called_once_with( signal.SIGCHLD) - m_new_add_signal_handler.assert_called_once_with( + m_new_add.assert_called_once_with( signal.SIGCHLD, self.watcher._sig_chld) # child terminates @@ -1462,7 +1459,6 @@ def test_close(self, m): # register two children callback1 = mock.Mock() - callback2 = mock.Mock() with self.watcher: self.running = True diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -8,7 +8,6 @@ import _winapi import asyncio -from asyncio import test_utils from asyncio import _overlapped from asyncio import windows_events @@ -50,7 +49,7 @@ ADDRESS = r'\\.\pipe\test_double_bind-%s' % os.getpid() server1 = windows_events.PipeServer(ADDRESS) with self.assertRaises(PermissionError): - server2 = windows_events.PipeServer(ADDRESS) + windows_events.PipeServer(ADDRESS) server1.close() def test_pipe(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 11:32:15 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 26 Feb 2014 11:32:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio=3A_simplify_test?= =?utf-8?q?=5Fevents=2Epy=2C_don=27t_use_non_local_variables_and_don=27t_c?= =?utf-8?q?all?= Message-ID: <3fYtcH65cTz7LkN@mail.python.org> http://hg.python.org/cpython/rev/4236cbe85f68 changeset: 89397:4236cbe85f68 user: Victor Stinner date: Wed Feb 26 11:31:55 2014 +0100 summary: asyncio: simplify test_events.py, don't use non local variables and don't call assert methods in coroutines. It also simplify merges from Tulip to Trollius (Python 2 does not support non local variables). files: Lib/test/test_asyncio/test_events.py | 265 ++++---------- 1 files changed, 79 insertions(+), 186 deletions(-) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -1155,23 +1155,15 @@ @unittest.skipUnless(sys.platform != 'win32', "Don't support pipes for Windows") def test_write_pipe(self): - proto = MyWritePipeProto(loop=self.loop) - transport = None - rpipe, wpipe = os.pipe() pipeobj = io.open(wpipe, 'wb', 1024) - @asyncio.coroutine - def connect(): - nonlocal transport - t, p = yield from self.loop.connect_write_pipe( - lambda: proto, pipeobj) - self.assertIs(p, proto) - self.assertIs(t, proto.transport) - self.assertEqual('CONNECTED', proto.state) - transport = t - - self.loop.run_until_complete(connect()) + proto = MyWritePipeProto(loop=self.loop) + connect = self.loop.connect_write_pipe(lambda: proto, pipeobj) + transport, p = self.loop.run_until_complete(connect) + self.assertIs(p, proto) + self.assertIs(transport, proto.transport) + self.assertEqual('CONNECTED', proto.state) transport.write(b'1') test_utils.run_briefly(self.loop) @@ -1197,23 +1189,14 @@ @unittest.skipUnless(sys.platform != 'win32', "Don't support pipes for Windows") def test_write_pipe_disconnect_on_close(self): - proto = MyWritePipeProto(loop=self.loop) - transport = None - rsock, wsock = test_utils.socketpair() pipeobj = io.open(wsock.detach(), 'wb', 1024) - @asyncio.coroutine - def connect(): - nonlocal transport - t, p = yield from self.loop.connect_write_pipe(lambda: proto, - pipeobj) - self.assertIs(p, proto) - self.assertIs(t, proto.transport) - self.assertEqual('CONNECTED', proto.state) - transport = t - - self.loop.run_until_complete(connect()) + proto = MyWritePipeProto(loop=self.loop) + connect = self.loop.connect_write_pipe(lambda: proto, pipeobj) + transport, p = self.loop.run_until_complete(connect) + self.assertIs(p, proto) + self.assertIs(transport, proto.transport) self.assertEqual('CONNECTED', proto.state) transport.write(b'1') @@ -1231,23 +1214,15 @@ # older than 10.6 (Snow Leopard) @support.requires_mac_ver(10, 6) def test_write_pty(self): - proto = MyWritePipeProto(loop=self.loop) - transport = None - master, slave = os.openpty() slave_write_obj = io.open(slave, 'wb', 0) - @asyncio.coroutine - def connect(): - nonlocal transport - t, p = yield from self.loop.connect_write_pipe(lambda: proto, - slave_write_obj) - self.assertIs(p, proto) - self.assertIs(t, proto.transport) - self.assertEqual('CONNECTED', proto.state) - transport = t - - self.loop.run_until_complete(connect()) + proto = MyWritePipeProto(loop=self.loop) + connect = self.loop.connect_write_pipe(lambda: proto, slave_write_obj) + transport, p = self.loop.run_until_complete(connect) + self.assertIs(p, proto) + self.assertIs(transport, proto.transport) + self.assertEqual('CONNECTED', proto.state) transport.write(b'1') test_utils.run_briefly(self.loop) @@ -1369,20 +1344,13 @@ self.assertEqual(-signal.SIGKILL, returncode) def test_subprocess_exec(self): - proto = None - transp = None - prog = os.path.join(os.path.dirname(__file__), 'echo.py') - @asyncio.coroutine - def connect(): - nonlocal proto, transp - transp, proto = yield from self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_exec( + functools.partial(MySubprocessProtocol, self.loop), + sys.executable, prog) + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.connected) self.assertEqual('CONNECTED', proto.state) @@ -1395,20 +1363,13 @@ self.assertEqual(b'Python The Winner', proto.data[1]) def test_subprocess_interactive(self): - proto = None - transp = None - prog = os.path.join(os.path.dirname(__file__), 'echo.py') - @asyncio.coroutine - def connect(): - nonlocal proto, transp - transp, proto = yield from self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_exec( + functools.partial(MySubprocessProtocol, self.loop), + sys.executable, prog) + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.connected) self.assertEqual('CONNECTED', proto.state) @@ -1429,18 +1390,11 @@ self.check_terminated(proto.returncode) def test_subprocess_shell(self): - proto = None - transp = None - - @asyncio.coroutine - def connect(): - nonlocal proto, transp - transp, proto = yield from self.loop.subprocess_shell( - functools.partial(MySubprocessProtocol, self.loop), - 'echo Python') - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_shell( + functools.partial(MySubprocessProtocol, self.loop), + 'echo Python') + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.connected) transp.get_pipe_transport(0).close() @@ -1451,33 +1405,20 @@ self.assertEqual(proto.data[2], b'') def test_subprocess_exitcode(self): - proto = None - - @asyncio.coroutine - def connect(): - nonlocal proto - transp, proto = yield from self.loop.subprocess_shell( - functools.partial(MySubprocessProtocol, self.loop), - 'exit 7', stdin=None, stdout=None, stderr=None) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_shell( + functools.partial(MySubprocessProtocol, self.loop), + 'exit 7', stdin=None, stdout=None, stderr=None) + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.completed) self.assertEqual(7, proto.returncode) def test_subprocess_close_after_finish(self): - proto = None - transp = None - - @asyncio.coroutine - def connect(): - nonlocal proto, transp - transp, proto = yield from self.loop.subprocess_shell( - functools.partial(MySubprocessProtocol, self.loop), - 'exit 7', stdin=None, stdout=None, stderr=None) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_shell( + functools.partial(MySubprocessProtocol, self.loop), + 'exit 7', stdin=None, stdout=None, stderr=None) + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.assertIsNone(transp.get_pipe_transport(0)) self.assertIsNone(transp.get_pipe_transport(1)) self.assertIsNone(transp.get_pipe_transport(2)) @@ -1486,20 +1427,13 @@ self.assertIsNone(transp.close()) def test_subprocess_kill(self): - proto = None - transp = None - prog = os.path.join(os.path.dirname(__file__), 'echo.py') - @asyncio.coroutine - def connect(): - nonlocal proto, transp - transp, proto = yield from self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_exec( + functools.partial(MySubprocessProtocol, self.loop), + sys.executable, prog) + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.connected) transp.kill() @@ -1507,20 +1441,13 @@ self.check_killed(proto.returncode) def test_subprocess_terminate(self): - proto = None - transp = None - prog = os.path.join(os.path.dirname(__file__), 'echo.py') - @asyncio.coroutine - def connect(): - nonlocal proto, transp - transp, proto = yield from self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_exec( + functools.partial(MySubprocessProtocol, self.loop), + sys.executable, prog) + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.connected) transp.terminate() @@ -1529,20 +1456,13 @@ @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") def test_subprocess_send_signal(self): - proto = None - transp = None - prog = os.path.join(os.path.dirname(__file__), 'echo.py') - @asyncio.coroutine - def connect(): - nonlocal proto, transp - transp, proto = yield from self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_exec( + functools.partial(MySubprocessProtocol, self.loop), + sys.executable, prog) + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.connected) transp.send_signal(signal.SIGHUP) @@ -1550,20 +1470,13 @@ self.assertEqual(-signal.SIGHUP, proto.returncode) def test_subprocess_stderr(self): - proto = None - transp = None - prog = os.path.join(os.path.dirname(__file__), 'echo2.py') - @asyncio.coroutine - def connect(): - nonlocal proto, transp - transp, proto = yield from self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_exec( + functools.partial(MySubprocessProtocol, self.loop), + sys.executable, prog) + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.connected) stdin = transp.get_pipe_transport(0) @@ -1577,20 +1490,13 @@ self.assertEqual(0, proto.returncode) def test_subprocess_stderr_redirect_to_stdout(self): - proto = None - transp = None - prog = os.path.join(os.path.dirname(__file__), 'echo2.py') - @asyncio.coroutine - def connect(): - nonlocal proto, transp - transp, proto = yield from self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog, stderr=subprocess.STDOUT) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_exec( + functools.partial(MySubprocessProtocol, self.loop), + sys.executable, prog, stderr=subprocess.STDOUT) + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.connected) stdin = transp.get_pipe_transport(0) @@ -1607,20 +1513,13 @@ self.assertEqual(0, proto.returncode) def test_subprocess_close_client_stream(self): - proto = None - transp = None - prog = os.path.join(os.path.dirname(__file__), 'echo3.py') - @asyncio.coroutine - def connect(): - nonlocal proto, transp - transp, proto = yield from self.loop.subprocess_exec( - functools.partial(MySubprocessProtocol, self.loop), - sys.executable, prog) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + connect = self.loop.subprocess_exec( + functools.partial(MySubprocessProtocol, self.loop), + sys.executable, prog) + transp, proto = self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.connected) stdin = transp.get_pipe_transport(0) @@ -1646,19 +1545,13 @@ self.check_terminated(proto.returncode) def test_subprocess_wait_no_same_group(self): - proto = None - - @asyncio.coroutine - def connect(): - nonlocal proto - # start the new process in a new session - _, proto = yield from self.loop.subprocess_shell( - functools.partial(MySubprocessProtocol, self.loop), - 'exit 7', stdin=None, stdout=None, stderr=None, - start_new_session=True) - self.assertIsInstance(proto, MySubprocessProtocol) - - self.loop.run_until_complete(connect()) + # start the new process in a new session + connect = self.loop.subprocess_shell( + functools.partial(MySubprocessProtocol, self.loop), + 'exit 7', stdin=None, stdout=None, stderr=None, + start_new_session=True) + _, proto = yield self.loop.run_until_complete(connect) + self.assertIsInstance(proto, MySubprocessProtocol) self.loop.run_until_complete(proto.completed) self.assertEqual(7, proto.returncode) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 16:39:06 2014 From: python-checkins at python.org (zach.ware) Date: Wed, 26 Feb 2014 16:39:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNzU5?= =?utf-8?q?=3A_Fix_some_typos_in_the_mock_docs=2E?= Message-ID: <3fZ1QL253Gz7LjX@mail.python.org> http://hg.python.org/cpython/rev/045f048cc116 changeset: 89398:045f048cc116 branch: 3.3 parent: 89393:8899e4028561 user: Zachary Ware date: Wed Feb 26 09:34:43 2014 -0600 summary: Issue #20759: Fix some typos in the mock docs. files: Doc/library/unittest.mock-examples.rst | 2 +- Doc/library/unittest.mock.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -412,7 +412,7 @@ As an alternative `patch`, `patch.object` and `patch.dict` can be used as class decorators. When used in this way it is the same as applying the -decorator indvidually to every method whose name starts with "test". +decorator individually to every method whose name starts with "test". .. _further-examples: diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -938,7 +938,7 @@ .. [#] The only exceptions are magic methods and attributes (those that have leading and trailing double underscores). Mock doesn't create these but - instead of raises an ``AttributeError``. This is because the interpreter + instead raises an ``AttributeError``. This is because the interpreter will often implicitly request these methods, and gets *very* confused to get a new Mock object when it expects a magic method. If you need magic method support see :ref:`magic methods `. @@ -1489,7 +1489,7 @@ Both patch_ and patch.object_ correctly patch and restore descriptors: class methods, static methods and properties. You should patch these on the *class* rather than an instance. They also work with *some* objects -that proxy attribute access, like the `django setttings object +that proxy attribute access, like the `django settings object `_. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 16:39:07 2014 From: python-checkins at python.org (zach.ware) Date: Wed, 26 Feb 2014 16:39:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Close_=2320759=3A_Fix_some_typos_in_the_mock_docs=2E_=28?= =?utf-8?q?Merge_with_3=2E3=29?= Message-ID: <3fZ1QM3xJtz7N5g@mail.python.org> http://hg.python.org/cpython/rev/42ef1c82d645 changeset: 89399:42ef1c82d645 parent: 89397:4236cbe85f68 parent: 89398:045f048cc116 user: Zachary Ware date: Wed Feb 26 09:38:39 2014 -0600 summary: Close #20759: Fix some typos in the mock docs. (Merge with 3.3) files: Doc/library/unittest.mock-examples.rst | 2 +- Doc/library/unittest.mock.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/unittest.mock-examples.rst b/Doc/library/unittest.mock-examples.rst --- a/Doc/library/unittest.mock-examples.rst +++ b/Doc/library/unittest.mock-examples.rst @@ -426,7 +426,7 @@ As an alternative `patch`, `patch.object` and `patch.dict` can be used as class decorators. When used in this way it is the same as applying the -decorator indvidually to every method whose name starts with "test". +decorator individually to every method whose name starts with "test". .. _further-examples: diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -958,7 +958,7 @@ .. [#] The only exceptions are magic methods and attributes (those that have leading and trailing double underscores). Mock doesn't create these but - instead of raises an ``AttributeError``. This is because the interpreter + instead raises an ``AttributeError``. This is because the interpreter will often implicitly request these methods, and gets *very* confused to get a new Mock object when it expects a magic method. If you need magic method support see :ref:`magic methods `. @@ -1509,7 +1509,7 @@ Both patch_ and patch.object_ correctly patch and restore descriptors: class methods, static methods and properties. You should patch these on the *class* rather than an instance. They also work with *some* objects -that proxy attribute access, like the `django setttings object +that proxy attribute access, like the `django settings object `_. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 17:37:25 2014 From: python-checkins at python.org (victor.stinner) Date: Wed, 26 Feb 2014 17:37:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_asyncio/windows=5Fevents?= =?utf-8?q?=2Epy=3A_use_more_revelant_names_to_overlapped_callbacks?= Message-ID: <3fZ2jd240Xz7LjS@mail.python.org> http://hg.python.org/cpython/rev/f686cf9be887 changeset: 89400:f686cf9be887 user: Victor Stinner date: Wed Feb 26 17:35:30 2014 +0100 summary: asyncio/windows_events.py: use more revelant names to overlapped callbacks For example: "finish_recv", not just "finish". files: Lib/asyncio/selector_events.py | 3 +-- Lib/asyncio/windows_events.py | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -702,8 +702,7 @@ if self._buffer: try: n = self._sock.send(self._buffer) - except (BlockingIOError, InterruptedError, - ssl.SSLWantWriteError): + except (BlockingIOError, InterruptedError, ssl.SSLWantWriteError): n = 0 except ssl.SSLWantReadError: n = 0 diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -213,7 +213,7 @@ else: ov.ReadFile(conn.fileno(), nbytes) - def finish(trans, key, ov): + def finish_recv(trans, key, ov): try: return ov.getresult() except OSError as exc: @@ -222,7 +222,7 @@ else: raise - return self._register(ov, conn, finish) + return self._register(ov, conn, finish_recv) def send(self, conn, buf, flags=0): self._register_with_iocp(conn) @@ -232,7 +232,7 @@ else: ov.WriteFile(conn.fileno(), buf) - def finish(trans, key, ov): + def finish_send(trans, key, ov): try: return ov.getresult() except OSError as exc: @@ -241,7 +241,7 @@ else: raise - return self._register(ov, conn, finish) + return self._register(ov, conn, finish_send) def accept(self, listener): self._register_with_iocp(listener) @@ -300,17 +300,17 @@ ov = _overlapped.Overlapped(NULL) ov.ConnectNamedPipe(pipe.fileno()) - def finish(trans, key, ov): + def finish_accept_pipe(trans, key, ov): ov.getresult() return pipe - return self._register(ov, pipe, finish) + return self._register(ov, pipe, finish_accept_pipe) def connect_pipe(self, address): ov = _overlapped.Overlapped(NULL) ov.WaitNamedPipeAndConnect(address, self._iocp, ov.address) - def finish(err, handle, ov): + def finish_connect_pipe(err, handle, ov): # err, handle were arguments passed to PostQueuedCompletionStatus() # in a function run in a thread pool. if err == _overlapped.ERROR_SEM_TIMEOUT: @@ -323,7 +323,7 @@ else: return windows_utils.PipeHandle(handle) - return self._register(ov, None, finish, wait_for_post=True) + return self._register(ov, None, finish_connect_pipe, wait_for_post=True) def wait_for_handle(self, handle, timeout=None): if timeout is None: @@ -339,7 +339,7 @@ handle, self._iocp, ov.address, ms) f = _WaitHandleFuture(wh, loop=self._loop) - def finish(trans, key, ov): + def finish_wait_for_handle(trans, key, ov): if not f.cancelled(): try: _overlapped.UnregisterWait(wh) @@ -355,7 +355,7 @@ return (_winapi.WaitForSingleObject(handle, 0) == _winapi.WAIT_OBJECT_0) - self._cache[ov.address] = (f, ov, None, finish) + self._cache[ov.address] = (f, ov, None, finish_wait_for_handle) return f def _register_with_iocp(self, obj): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 17:42:58 2014 From: python-checkins at python.org (zach.ware) Date: Wed, 26 Feb 2014 17:42:58 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Fix_several_C-?= =?utf-8?q?API_doc_typos_caught_by_tomo_cocoa_on_docs=40=2E?= Message-ID: <3fZ2r20R0Nz7LjS@mail.python.org> http://hg.python.org/cpython/rev/5c5a89f18ba1 changeset: 89401:5c5a89f18ba1 branch: 3.3 parent: 89398:045f048cc116 user: Zachary Ware date: Wed Feb 26 10:40:38 2014 -0600 summary: Fix several C-API doc typos caught by tomo cocoa on docs at . The signature and description of PyException_SetCause now use "cause" rather than "ctx" to match the code. files: Doc/c-api/exceptions.rst | 10 +++++----- Doc/c-api/module.rst | 2 +- Doc/c-api/typeobj.rst | 5 ++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -306,7 +306,7 @@ .. c:function:: void PyErr_SyntaxLocation(char *filename, int lineno) - Like :c:func:`PyErr_SyntaxLocationExc`, but the col_offset parameter is + Like :c:func:`PyErr_SyntaxLocationEx`, but the col_offset parameter is omitted. @@ -490,11 +490,11 @@ reference, as accessible from Python through :attr:`__cause__`. -.. c:function:: void PyException_SetCause(PyObject *ex, PyObject *ctx) +.. c:function:: void PyException_SetCause(PyObject *ex, PyObject *cause) - Set the cause associated with the exception to *ctx*. Use *NULL* to clear - it. There is no type check to make sure that *ctx* is either an exception - instance or :const:`None`. This steals a reference to *ctx*. + Set the cause associated with the exception to *cause*. Use *NULL* to clear + it. There is no type check to make sure that *cause* is either an exception + instance or :const:`None`. This steals a reference to *cause*. :attr:`__suppress_context__` is implicitly set to ``True`` by this function. diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -113,7 +113,7 @@ Return a pointer to the :c:type:`PyModuleDef` struct from which the module was created, or *NULL* if the module wasn't created with - :c:func:`PyModule_Create`.i + :c:func:`PyModule_Create`. .. c:function:: PyObject* PyState_FindModule(PyModuleDef *def) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -205,9 +205,8 @@ bit currently defined is :const:`Py_PRINT_RAW`. When the :const:`Py_PRINT_RAW` flag bit is set, the instance should be printed the same way as :c:member:`~PyTypeObject.tp_str` would format it; when the :const:`Py_PRINT_RAW` flag bit is clear, the instance - should be printed the same was as :c:member:`~PyTypeObject.tp_repr` would format it. It should - return ``-1`` and set an exception condition when an error occurred during the - comparison. + should be printed the same way as :c:member:`~PyTypeObject.tp_repr` would format it. It should + return ``-1`` and set an exception condition when an error occurs. It is possible that the :c:member:`~PyTypeObject.tp_print` field will be deprecated. In any case, it is recommended not to define :c:member:`~PyTypeObject.tp_print`, but instead to rely on -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 17:42:59 2014 From: python-checkins at python.org (zach.ware) Date: Wed, 26 Feb 2014 17:42:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3fZ2r335xtz7LjS@mail.python.org> http://hg.python.org/cpython/rev/aaef9e79c19a changeset: 89402:aaef9e79c19a parent: 89400:f686cf9be887 parent: 89401:5c5a89f18ba1 user: Zachary Ware date: Wed Feb 26 10:41:40 2014 -0600 summary: Merge with 3.3 files: Doc/c-api/exceptions.rst | 8 ++++---- Doc/c-api/module.rst | 2 +- Doc/c-api/typeobj.rst | 5 ++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -525,11 +525,11 @@ reference, as accessible from Python through :attr:`__cause__`. -.. c:function:: void PyException_SetCause(PyObject *ex, PyObject *ctx) +.. c:function:: void PyException_SetCause(PyObject *ex, PyObject *cause) - Set the cause associated with the exception to *ctx*. Use *NULL* to clear - it. There is no type check to make sure that *ctx* is either an exception - instance or :const:`None`. This steals a reference to *ctx*. + Set the cause associated with the exception to *cause*. Use *NULL* to clear + it. There is no type check to make sure that *cause* is either an exception + instance or :const:`None`. This steals a reference to *cause*. :attr:`__suppress_context__` is implicitly set to ``True`` by this function. diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst --- a/Doc/c-api/module.rst +++ b/Doc/c-api/module.rst @@ -120,7 +120,7 @@ Return a pointer to the :c:type:`PyModuleDef` struct from which the module was created, or *NULL* if the module wasn't created with - :c:func:`PyModule_Create`.i + :c:func:`PyModule_Create`. .. c:function:: PyObject* PyState_FindModule(PyModuleDef *def) diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -205,9 +205,8 @@ bit currently defined is :const:`Py_PRINT_RAW`. When the :const:`Py_PRINT_RAW` flag bit is set, the instance should be printed the same way as :c:member:`~PyTypeObject.tp_str` would format it; when the :const:`Py_PRINT_RAW` flag bit is clear, the instance - should be printed the same was as :c:member:`~PyTypeObject.tp_repr` would format it. It should - return ``-1`` and set an exception condition when an error occurred during the - comparison. + should be printed the same way as :c:member:`~PyTypeObject.tp_repr` would format it. It should + return ``-1`` and set an exception condition when an error occurs. It is possible that the :c:member:`~PyTypeObject.tp_print` field will be deprecated. In any case, it is recommended not to define :c:member:`~PyTypeObject.tp_print`, but instead to rely on -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 20:05:27 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 26 Feb 2014 20:05:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTAx?= =?utf-8?q?=3A_fileinput_module_no_longer_reads_whole_file_into_memory_whe?= =?utf-8?q?n_using?= Message-ID: <3fZ60R5n8GzRYc@mail.python.org> http://hg.python.org/cpython/rev/1a1a9d6fb278 changeset: 89403:1a1a9d6fb278 branch: 2.7 parent: 89378:0926adcc335c user: Serhiy Storchaka date: Wed Feb 26 20:59:08 2014 +0200 summary: Issue #20501: fileinput module no longer reads whole file into memory when using fileinput.hook_encoded. files: Lib/fileinput.py | 5 +- Lib/test/test_fileinput.py | 43 +++++++++++++++++++++++++- Misc/NEWS | 3 + 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/Lib/fileinput.py b/Lib/fileinput.py --- a/Lib/fileinput.py +++ b/Lib/fileinput.py @@ -387,9 +387,10 @@ def hook_encoded(encoding): - import codecs + import io def openhook(filename, mode): - return codecs.open(filename, mode, encoding) + mode = mode.replace('U', '').replace('b', '') or 'r' + return io.open(filename, mode, encoding=encoding, newline='') return openhook diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py --- a/Lib/test/test_fileinput.py +++ b/Lib/test/test_fileinput.py @@ -218,8 +218,49 @@ finally: remove_tempfiles(t1) + def test_readline(self): + with open(TESTFN, 'wb') as f: + f.write('A\nB\r\nC\r') + # Fill TextIOWrapper buffer. + f.write('123456789\n' * 1000) + # Issue #20501: readline() shouldn't read whole file. + f.write('\x80') + self.addCleanup(safe_unlink, TESTFN) + + fi = FileInput(files=TESTFN, openhook=hook_encoded('ascii'), bufsize=8) + self.assertEqual(fi.readline(), u'A\n') + self.assertEqual(fi.readline(), u'B\r\n') + self.assertEqual(fi.readline(), u'C\r') + with self.assertRaises(UnicodeDecodeError): + # Read to the end of file. + list(fi) + fi.close() + +class Test_hook_encoded(unittest.TestCase): + """Unit tests for fileinput.hook_encoded()""" + + def test_modes(self): + # Unlikely UTF-7 is locale encoding + with open(TESTFN, 'wb') as f: + f.write('A\nB\r\nC\rD+IKw-') + t1 = TESTFN + #t1 = writeTmp(1, ['A\nB\r\nC\rD+IKw-'], mode='wb') + self.addCleanup(safe_unlink, TESTFN) + + def check(mode, expected_lines): + fi = FileInput(files=TESTFN, mode=mode, + openhook=hook_encoded('utf-7')) + lines = list(fi) + fi.close() + self.assertEqual(lines, expected_lines) + + check('r', [u'A\n', u'B\r\n', u'C\r', u'D\u20ac']) + check('rU', [u'A\n', u'B\r\n', u'C\r', u'D\u20ac']) + check('U', [u'A\n', u'B\r\n', u'C\r', u'D\u20ac']) + check('rb', [u'A\n', u'B\r\n', u'C\r', u'D\u20ac']) + def test_main(): - run_unittest(BufferSizesTests, FileInputTests) + run_unittest(BufferSizesTests, FileInputTests, Test_hook_encoded) if __name__ == "__main__": test_main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -40,6 +40,9 @@ Library ------- +- Issue #20501: fileinput module no longer reads whole file into memory when using + fileinput.hook_encoded. + - Issue #6815: os.path.expandvars() now supports non-ASCII Unicode environment variables names and values. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 20:05:29 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 26 Feb 2014 20:05:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Added_tests_fo?= =?utf-8?q?r_issue_=2320501=2E?= Message-ID: <3fZ60T09j5z7Lkp@mail.python.org> http://hg.python.org/cpython/rev/b4a139713b3b changeset: 89404:b4a139713b3b branch: 3.3 parent: 89401:5c5a89f18ba1 user: Serhiy Storchaka date: Wed Feb 26 20:59:43 2014 +0200 summary: Added tests for issue #20501. files: Lib/test/test_fileinput.py | 36 ++++++++++++++++++++++++++ 1 files changed, 36 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py --- a/Lib/test/test_fileinput.py +++ b/Lib/test/test_fileinput.py @@ -258,6 +258,24 @@ fi.readline() self.assertTrue(custom_open_hook.invoked, "openhook not invoked") + def test_readline(self): + with open(TESTFN, 'wb') as f: + f.write(b'A\nB\r\nC\r') + # Fill TextIOWrapper buffer. + f.write(b'123456789\n' * 1000) + # Issue #20501: readline() shouldn't read whole file. + f.write(b'\x80') + self.addCleanup(safe_unlink, TESTFN) + + with FileInput(files=TESTFN, + openhook=hook_encoded('ascii'), bufsize=8) as fi: + self.assertEqual(fi.readline(), 'A\n') + self.assertEqual(fi.readline(), 'B\n') + self.assertEqual(fi.readline(), 'C\n') + with self.assertRaises(UnicodeDecodeError): + # Read to the end of file. + list(fi) + def test_context_manager(self): try: t1 = writeTmp(1, ["A\nB\nC"]) @@ -835,6 +853,24 @@ self.assertIs(kwargs.pop('encoding'), encoding) self.assertFalse(kwargs) + def test_modes(self): + # Unlikely UTF-7 is locale encoding + with open(TESTFN, 'wb') as f: + f.write(b'A\nB\r\nC\rD+IKw-') + self.addCleanup(safe_unlink, TESTFN) + + def check(mode, expected_lines): + with FileInput(files=TESTFN, mode=mode, + openhook=hook_encoded('utf-7')) as fi: + lines = list(fi) + self.assertEqual(lines, expected_lines) + + check('r', ['A\n', 'B\n', 'C\n', 'D\u20ac']) + check('rU', ['A\n', 'B\n', 'C\n', 'D\u20ac']) + check('U', ['A\n', 'B\n', 'C\n', 'D\u20ac']) + with self.assertRaises(ValueError): + check('rb', ['A\n', 'B\r\n', 'C\r', 'D\u20ac']) + def test_main(): run_unittest( BufferSizesTests, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Feb 26 20:05:30 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 26 Feb 2014 20:05:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Added_tests_for_issue_=2320501=2E?= Message-ID: <3fZ60V1kD7z7Lkr@mail.python.org> http://hg.python.org/cpython/rev/1a38fa1f701d changeset: 89405:1a38fa1f701d parent: 89402:aaef9e79c19a parent: 89404:b4a139713b3b user: Serhiy Storchaka date: Wed Feb 26 21:03:19 2014 +0200 summary: Added tests for issue #20501. files: Lib/test/test_fileinput.py | 38 ++++++++++++++++++++++++++ 1 files changed, 38 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py --- a/Lib/test/test_fileinput.py +++ b/Lib/test/test_fileinput.py @@ -260,6 +260,24 @@ fi.readline() self.assertTrue(custom_open_hook.invoked, "openhook not invoked") + def test_readline(self): + with open(TESTFN, 'wb') as f: + f.write(b'A\nB\r\nC\r') + # Fill TextIOWrapper buffer. + f.write(b'123456789\n' * 1000) + # Issue #20501: readline() shouldn't read whole file. + f.write(b'\x80') + self.addCleanup(safe_unlink, TESTFN) + + with FileInput(files=TESTFN, + openhook=hook_encoded('ascii'), bufsize=8) as fi: + self.assertEqual(fi.readline(), 'A\n') + self.assertEqual(fi.readline(), 'B\n') + self.assertEqual(fi.readline(), 'C\n') + with self.assertRaises(UnicodeDecodeError): + # Read to the end of file. + list(fi) + def test_context_manager(self): try: t1 = writeTmp(1, ["A\nB\nC"]) @@ -837,6 +855,26 @@ self.assertIs(kwargs.pop('encoding'), encoding) self.assertFalse(kwargs) + def test_modes(self): + # Unlikely UTF-7 is locale encoding + with open(TESTFN, 'wb') as f: + f.write(b'A\nB\r\nC\rD+IKw-') + self.addCleanup(safe_unlink, TESTFN) + + def check(mode, expected_lines): + with FileInput(files=TESTFN, mode=mode, + openhook=hook_encoded('utf-7')) as fi: + lines = list(fi) + self.assertEqual(lines, expected_lines) + + check('r', ['A\n', 'B\n', 'C\n', 'D\u20ac']) + with self.assertWarns(DeprecationWarning): + check('rU', ['A\n', 'B\n', 'C\n', 'D\u20ac']) + with self.assertWarns(DeprecationWarning): + check('U', ['A\n', 'B\n', 'C\n', 'D\u20ac']) + with self.assertRaises(ValueError): + check('rb', ['A\n', 'B\r\n', 'C\r', 'D\u20ac']) + if __name__ == "__main__": unittest.main() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 27 00:26:57 2014 From: python-checkins at python.org (brett.cannon) Date: Thu, 27 Feb 2014 00:26:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320763=3A_Fix_impo?= =?utf-8?q?rtlib=2Emachinery=2EPathFinder_to_support?= Message-ID: <3fZCp90GB7z7LjX@mail.python.org> http://hg.python.org/cpython/rev/5dec1604322c changeset: 89406:5dec1604322c user: Brett Cannon date: Wed Feb 26 18:26:49 2014 -0500 summary: Issue #20763: Fix importlib.machinery.PathFinder to support PathEntryFinder instances which only define find_module(). Reported by Yukihiro Nakadaira. files: Lib/importlib/_bootstrap.py | 2 +- Lib/test/test_importlib/import_/test_path.py | 24 ++++++++++ Python/importlib.h | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -1869,7 +1869,7 @@ loader, portions = finder.find_loader(fullname) else: loader = finder.find_module(fullname) - portions = None + portions = [] if loader is not None: return spec_from_loader(fullname, loader) spec = ModuleSpec(fullname, None) diff --git a/Lib/test/test_importlib/import_/test_path.py b/Lib/test/test_importlib/import_/test_path.py --- a/Lib/test/test_importlib/import_/test_path.py +++ b/Lib/test/test_importlib/import_/test_path.py @@ -116,5 +116,29 @@ FinderTests, importlib=importlib, machinery=machinery) +class PathEntryFinderTests: + + def test_finder_with_failing_find_module(self): + # PathEntryFinder with find_module() defined should work. + # Issue #20763. + class Finder: + path_location = 'test_finder_with_find_module' + def __init__(self, path): + if path != self.path_location: + raise ImportError + + @staticmethod + def find_module(fullname): + return None + + + with util.import_state(path=[Finder.path_location]+sys.path[:], + path_hooks=[Finder]): + self.machinery.PathFinder.find_spec('importlib') + +Frozen_PEFTests, Source_PEFTests = util.test_both( + PathEntryFinderTests, machinery=machinery) + + if __name__ == '__main__': unittest.main() diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Feb 27 09:55:47 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 27 Feb 2014 09:55:47 +0100 Subject: [Python-checkins] Daily reference leaks (5dec1604322c): sum=4 Message-ID: results for 5dec1604322c on branch "default" -------------------------------------------- test_site leaked [0, 2, 0] references, sum=2 test_site leaked [0, 2, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogoOG0_1', '-x'] From python-checkins at python.org Thu Feb 27 19:50:37 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 27 Feb 2014 19:50:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_fix_importlib_?= =?utf-8?q?test_failure_when_bytecode_writing_is_disabled_=28closes_=23207?= =?utf-8?b?OTYp?= Message-ID: <3fZjcs4Mgkz7Lnh@mail.python.org> http://hg.python.org/cpython/rev/8afcfe6dfd6e changeset: 89407:8afcfe6dfd6e branch: 3.3 parent: 89404:b4a139713b3b user: Benjamin Peterson date: Thu Feb 27 13:49:34 2014 -0500 summary: fix importlib test failure when bytecode writing is disabled (closes #20796) Patch by Berker Peksag. files: Lib/test/test_importlib/source/test_file_loader.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_importlib/source/test_file_loader.py b/Lib/test/test_importlib/source/test_file_loader.py --- a/Lib/test/test_importlib/source/test_file_loader.py +++ b/Lib/test/test_importlib/source/test_file_loader.py @@ -162,6 +162,7 @@ if os.path.exists(pycache): shutil.rmtree(pycache) + @source_util.writes_bytecode_files def test_timestamp_overflow(self): # When a modification timestamp is larger than 2**32, it should be # truncated rather than raise an OverflowError. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 27 19:50:38 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 27 Feb 2014 19:50:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4zICgjMjA3OTYp?= Message-ID: <3fZjct6CFbz7Lnx@mail.python.org> http://hg.python.org/cpython/rev/15a0bbfb27f1 changeset: 89408:15a0bbfb27f1 parent: 89406:5dec1604322c parent: 89407:8afcfe6dfd6e user: Benjamin Peterson date: Thu Feb 27 13:50:28 2014 -0500 summary: merge 3.3 (#20796) files: Lib/test/test_importlib/source/test_file_loader.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_importlib/source/test_file_loader.py b/Lib/test/test_importlib/source/test_file_loader.py --- a/Lib/test/test_importlib/source/test_file_loader.py +++ b/Lib/test/test_importlib/source/test_file_loader.py @@ -190,6 +190,7 @@ if os.path.exists(pycache): shutil.rmtree(pycache) + @source_util.writes_bytecode_files def test_timestamp_overflow(self): # When a modification timestamp is larger than 2**32, it should be # truncated rather than raise an OverflowError. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 27 22:16:05 2014 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 27 Feb 2014 22:16:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320791=3A_copy=2Ec?= =?utf-8?q?opy=28=29_now_doesn=27t_make_a_copy_when_the_input_is_a_bytes?= Message-ID: <3fZmrj2FY8z7Lk9@mail.python.org> http://hg.python.org/cpython/rev/c2523bca50d7 changeset: 89409:c2523bca50d7 user: Antoine Pitrou date: Thu Feb 27 22:14:31 2014 +0100 summary: Issue #20791: copy.copy() now doesn't make a copy when the input is a bytes object. Initial patch by Peter Otten. files: Lib/copy.py | 2 +- Lib/test/test_copy.py | 1 + Misc/NEWS | 3 +++ 3 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/copy.py b/Lib/copy.py --- a/Lib/copy.py +++ b/Lib/copy.py @@ -110,7 +110,7 @@ def _copy_immutable(x): return x for t in (type(None), int, float, bool, str, tuple, - frozenset, type, range, + bytes, frozenset, type, range, types.BuiltinFunctionType, type(Ellipsis), types.FunctionType, weakref.ref): d[t] = _copy_immutable diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -98,6 +98,7 @@ pass tests = [None, 42, 2**100, 3.14, True, False, 1j, "hello", "hello\u1234", f.__code__, + b"world", bytes(range(256)), NewStyle, range(10), Classic, max, WithMetaclass] for x in tests: self.assertIs(copy.copy(x), x) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -14,6 +14,9 @@ Library ------- +- Issue #20791: copy.copy() now doesn't make a copy when the input is + a bytes object. Initial patch by Peter Otten. + - Issue #19748: On AIX, time.mktime() now raises an OverflowError for year outsize range [1902; 2037]. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Feb 27 23:32:14 2014 From: python-checkins at python.org (thomas.wouters) Date: Thu, 27 Feb 2014 23:32:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_PEP_463_with_Chris_Ang?= =?utf-8?q?elico=27s_latest_version=2C_with_slightly_fixed?= Message-ID: <3fZpXZ4Q7vz7LjW@mail.python.org> http://hg.python.org/peps/rev/2503db6ec908 changeset: 5387:2503db6ec908 user: Thomas Wouters date: Thu Feb 27 23:32:04 2014 +0100 summary: Update PEP 463 with Chris Angelico's latest version, with slightly fixed formatting. files: pep-0463.txt | 44 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 43 insertions(+), 1 deletions(-) diff --git a/pep-0463.txt b/pep-0463.txt --- a/pep-0463.txt +++ b/pep-0463.txt @@ -43,6 +43,34 @@ * statistics.mean(data) - no way to handle an empty iterator +Had this facility existed early in Python's history, there would have been +no need to create dict.get() and related methods; the one obvious way to +handle an absent key would be to respond to the exception. One method is +written which signals the absence in one way, and one consistent technique +is used to respond to the absence. Instead, we have dict.get(), and as of +Python 3.4, we also have min(... default=default), and myriad others. We +have a LBYL syntax for testing inside an expression, but there is currently +no EAFP notation; compare the following:: + + # LBYL: + if key in dic: + process(dic[key]) + else: + process(None) + # As an expression: + process(dic[key] if key in dic else None) + + # EAFP: + try: + process(dic[key]) + except KeyError: + process(None) + # As an expression: + process(dic[key] except KeyError: None) + +Python generally recommends the EAFP policy, but must then proliferate +utility functions like dic.get(key,None) to enable this. + Rationale ========= @@ -338,6 +366,20 @@ except KeyError: u = tarinfo.uid +Look up an attribute, falling back on a default:: + + mode = (f.mode except AttributeError: 'rb') + + # Lib/aifc.py:882: + if hasattr(f, 'mode'): + mode = f.mode + else: + mode = 'rb' + + return (sys._getframe(1) except AttributeError: None) + # Lib/inspect.py:1350: + return sys._getframe(1) if hasattr(sys, "_getframe") else None + Perform some lengthy calculations in EAFP mode, handling division by zero as a sort of sticky NaN:: @@ -616,7 +658,7 @@ it would be with the statement form, and as its syntax is a point on which consensus has not been reached, the entire feature is deferred. -Multiple 'except' keywords can be used, and they will all catch +Multiple 'except' keywords could be used, and they will all catch exceptions raised in the original expression (only):: # Will catch any of the listed exceptions thrown by expr; -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Thu Feb 27 23:37:34 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 27 Feb 2014 23:37:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_link_to_PEP_8?= Message-ID: <3fZpfk2XPJz7LjW@mail.python.org> http://hg.python.org/peps/rev/0fd8ec62bf8c changeset: 5388:0fd8ec62bf8c user: Benjamin Peterson date: Thu Feb 27 17:37:29 2014 -0500 summary: link to PEP 8 files: pep-0257.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0257.txt b/pep-0257.txt --- a/pep-0257.txt +++ b/pep-0257.txt @@ -297,7 +297,7 @@ .. _Docutils: http://docutils.sourceforge.net/ .. _Python Style Guide: - http://www.python.org/doc/essays/styleguide.html + (http://www.python.org/dev/peps/pep-0008/) .. _Doc-SIG: http://www.python.org/sigs/doc-sig/ -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Feb 28 00:12:07 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 28 Feb 2014 00:12:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_pprint=27s_com?= =?utf-8?q?pact_option=2E?= Message-ID: <3fZqQb3CsVz7LjW@mail.python.org> http://hg.python.org/cpython/rev/60a65b229119 changeset: 89410:60a65b229119 user: R David Murray date: Wed Feb 26 09:51:58 2014 -0500 summary: whatsnew: pprint's compact option. files: Doc/whatsnew/3.4.rst | 10 +++++++--- 1 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1043,11 +1043,15 @@ pprint ------ -The :mod:`pprint` module now supports *compact* mode for formatting long -sequences (:issue:`19132`). +The :mod:`pprint` module's :class:`~pprint.PrettyPrinter` class and its +:func:`~pprint.pformat`, and :func:`~pprint.pprint` functions have a new +option, *compact*, that controls how the output is formatted. Currently +setting *compact* to ``True`` means that sequences will be printed with as many +sequence elements as will fit within *width* on each (indented) line. +(Contributed by Serhiy Storchaka in :issue:`19132`.) Long strings are now wrapped using Python's normal line continuation -syntax (Contributed by Antoine Pitrou in :issue:`17150`.) +syntax. (Contributed by Antoine Pitrou in :issue:`17150`). pty -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 00:12:08 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 28 Feb 2014 00:12:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_attribute_base?= =?utf-8?q?64_memoryview_change_to_Nick=2E?= Message-ID: <3fZqQc4kPSz7LjW@mail.python.org> http://hg.python.org/cpython/rev/f6a82cbff9d2 changeset: 89411:f6a82cbff9d2 user: R David Murray date: Wed Feb 26 10:09:25 2014 -0500 summary: whatsnew: attribute base64 memoryview change to Nick. files: Doc/whatsnew/3.4.rst | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -558,7 +558,8 @@ The encoding and decoding functions in :mod:`base64` now accept any :term:`bytes-like object` in cases where it previously required a -:class:`bytes` or :class:`bytearray` instance (:issue:`17839`). +:class:`bytes` or :class:`bytearray` instance. (Contributed by Nick Coghlan in +:issue:`17839`.) colorsys -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 00:12:09 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 28 Feb 2014 00:12:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_reword_the_con?= =?utf-8?q?textlib=2Eredirect=5Fstdout_entry_for_increased_clarity=2E?= Message-ID: <3fZqQd6Trrz7Lnh@mail.python.org> http://hg.python.org/cpython/rev/02980840a341 changeset: 89412:02980840a341 user: R David Murray date: Wed Feb 26 12:46:19 2014 -0500 summary: whatsnew: reword the contextlib.redirect_stdout entry for increased clarity. files: Doc/whatsnew/3.4.rst | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -580,11 +580,15 @@ Zero Piraeus in :issue:`19266`) The new :func:`contextlib.redirect_stdout` context manager makes it easier -for utility scripts to handle inflexible APIs that don't provide any -options to retrieve their output as a string or direct it to somewhere -other than :data:`sys.stdout`. In conjunction with :class:`io.StringIO`, -this context manager is also useful for checking expected output from -command line utilities. (Contribute by Raymond Hettinger in :issue:`15805`) +for utility scripts to handle inflexible APIs that write their output to +:data:`sys.stdout` and don't provide any options to redirect it. Using the +context manager, the :data:`sys.stdout` output can be redirected to any +other stream or, in conjunction with :class:`io.StringIO`, to a string. +The latter can be especially useful, for example, to capture output +from a function that was written to implement a command line interface. +It is recommended only for utility scripts because it affects the +global state of :data:`sys.stdout`. (Contributed by Raymond Hettinger +in :issue:`15805`) The :mod:`contextlib` documentation has also been updated to include a :ref:`discussion ` of the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 00:12:11 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 28 Feb 2014 00:12:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_reformat_pdb_e?= =?utf-8?q?ntry_to_match_style_of_most_other_module_entries=2E?= Message-ID: <3fZqQg1F0Fz7Lkg@mail.python.org> http://hg.python.org/cpython/rev/a0765aefa497 changeset: 89413:a0765aefa497 user: R David Murray date: Wed Feb 26 12:52:51 2014 -0500 summary: whatsnew: reformat pdb entry to match style of most other module entries. That is: one paragraph per feature. files: Doc/whatsnew/3.4.rst | 18 ++++++++---------- 1 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -998,16 +998,14 @@ --- The ``print`` command has been removed from :mod:`pdb`, restoring access to the -``print`` function. - -Rationale: Python2's ``pdb`` did not have a ``print`` command; instead, -entering ``print`` executed the ``print`` statement. In Python3 ``print`` was -mistakenly made an alias for the pdb :pdbcmd:`p` command. ``p``, however, -prints the ``repr`` of its argument, not the ``str`` like the Python2 ``print`` -command did. Worse, the Python3 ``pdb print`` command shadowed the Python3 -``print`` function, making it inaccessible at the ``pdb`` prompt. - -(Contributed by Connor Osborn in :issue:`18764`.) +Python :func:`print` function from the pdb command line. Python2's ``pdb`` did +not have a ``print`` command; instead, entering ``print`` executed the +``print`` statement. In Python3 ``print`` was mistakenly made an alias for the +pdb :pdbcmd:`p` command. ``p``, however, prints the ``repr`` of its argument, +not the ``str`` like the Python2 ``print`` command did. Worse, the Python3 +``pdb print`` command shadowed the Python3 ``print`` function, making it +inaccessible at the ``pdb`` prompt. (Contributed by Connor Osborn in +:issue:`18764`.) .. _whatsnew-protocol-4: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 00:12:12 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 28 Feb 2014 00:12:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_expand_pbkdf2?= =?utf-8?q?=5Fhmac_entry_slightly=2E?= Message-ID: <3fZqQh334fz7LqX@mail.python.org> http://hg.python.org/cpython/rev/d3d6def8107b changeset: 89414:d3d6def8107b user: R David Murray date: Wed Feb 26 13:07:21 2014 -0500 summary: whatsnew: expand pbkdf2_hmac entry slightly. files: Doc/whatsnew/3.4.rst | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -757,8 +757,10 @@ hashlib ------- -New :func:`hashlib.pbkdf2_hmac` function. (Contributed by Christian Heimes in -:issue:`18582`) +A new :func:`hashlib.pbkdf2_hmac` function provides +the `PKCS#5 password-based key derivation function 2 +`_. (Contributed by Christian +Heimes in :issue:`18582`) The :attr:`~hashlib.hash.name` attribute of :mod:`hashlib` hash objects is now a formally supported interface. It has always existed in CPython's -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 00:12:13 2014 From: python-checkins at python.org (r.david.murray) Date: Fri, 28 Feb 2014 00:12:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_whatsnew=3A_fix_textwrap/s?= =?utf-8?q?horten_entry=2C_and_improve_the_related_docs=2E?= Message-ID: <3fZqQj64bNz7Lk9@mail.python.org> http://hg.python.org/cpython/rev/9e8605ef7099 changeset: 89415:9e8605ef7099 user: R David Murray date: Thu Feb 27 18:01:43 2014 -0500 summary: whatsnew: fix textwrap/shorten entry, and improve the related docs. I had incorrectly added back the shorten method when I initially made the whatsnew entry, but the shorten function docs were not correct according to the code. I also improved the wording in general. files: Doc/library/textwrap.rst | 39 ++++++++++++--------------- Doc/whatsnew/3.4.rst | 18 ++++++------ 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/Doc/library/textwrap.rst b/Doc/library/textwrap.rst --- a/Doc/library/textwrap.rst +++ b/Doc/library/textwrap.rst @@ -40,13 +40,14 @@ :func:`wrap`. -.. function:: shorten(text, width=70, *, placeholder=" [...]") +.. function:: shorten(text, width, **kwargs) - Collapse and truncate the given text to fit in the given width. + Collapse and truncate the given *text* to fit in the given *width*. - The text first has its whitespace collapsed. If it then fits in - the *width*, it is returned unchanged. Otherwise, as many words - as possible are joined and then the *placeholder* is appended:: + First the whitespace in *text* is collapsed (all whitespace is replaced by + single spaces). If the result fits in the *width*, it is returned. + Otherwise, enough words are dropped from the end so that the remaining words + plus the :attr:`placeholder` fit within :attr:`width`:: >>> textwrap.shorten("Hello world!", width=12) 'Hello world!' @@ -55,6 +56,12 @@ >>> textwrap.shorten("Hello world", width=10, placeholder="...") 'Hello...' + Optional keyword arguments correspond to the instance attributes of + :class:`TextWrapper`, documented below. Note that the whitespace is + collapsed before the text is passed to the :class:`TextWrapper` :meth:`fill` + function, so changing the value of :attr:`.tabsize`, :attr:`.expand_tabs`, + :attr:`.drop_whitespace`, and :attr:`.replace_whitespace` will have no effect. + .. versionadded:: 3.4 @@ -110,8 +117,8 @@ :func:`wrap`, :func:`fill` and :func:`shorten` work by creating a :class:`TextWrapper` instance and calling a single method on it. That instance is not reused, so for applications that process many text -strings, it may be more efficient to create your own -:class:`TextWrapper` object. +strings using :func:`wrap` and/or :func:`fill`, it may be more efficient to +create your own :class:`TextWrapper` object. Text is preferably wrapped on whitespaces and right after the hyphens in hyphenated words; only then will long words be broken if necessary, unless @@ -252,16 +259,16 @@ .. attribute:: max_lines - (default: ``None``) If not ``None``, then the text be will truncated to - *max_lines* lines. + (default: ``None``) If not ``None``, then the output will contain at most + *max_lines* lines, with *placeholder* appearing at the end of the output. .. versionadded:: 3.4 .. attribute:: placeholder - (default: ``' [...]'``) String that will be appended to the last line of - text if it will be truncated. + (default: ``' [...]'``) String that will appear at the end of the output + text if it has been truncated. .. versionadded:: 3.4 @@ -282,13 +289,3 @@ Wraps the single paragraph in *text*, and returns a single string containing the wrapped paragraph. - - - .. method:: shorten(text, width=70, *, placeholder=" [...]") - - Collapse and truncate the given text to fit in the given width. - The text first has its whitespace collapsed. If it then fits in - the *width*, it is returned unchanged. Otherwise, as many words - as possible are joined and then the *placeholder* is appended. - - .. versionadded:: 3.4 diff --git a/Doc/whatsnew/3.4.rst b/Doc/whatsnew/3.4.rst --- a/Doc/whatsnew/3.4.rst +++ b/Doc/whatsnew/3.4.rst @@ -1250,15 +1250,15 @@ textwrap -------- -:mod:`textwrap` has a new function :func:`~textwrap.shorten`, implemented via a -new :class:`~textwrap.TextWrapper` method -:meth:`~textwrap.TextWrapper.shorten`, that provides a convenient way to create -a string that displays just the leading porting of an input string. It -collapses any whitespace, truncates the result to a specified width, and a -specified placeholder is added (by default, ``[...]``, stored in the new -:attr:`~textwrap.TextWrapper.placeholder` attribute of the -:class:`~textwrap.TextWrapper` object)). (Contributed by Antoine Pitrou in -:issue:`18585`.) +The :class:`~textwrap.TextWrapper` class has two new attributes/constructor +arguments: :attr:`~textwrap.TextWrapper.max_lines`, which limits the number of +lines in the output, and :attr:`~textwrap.TextWrapper.placeholder`, which is a +string that will appear at the end of the output if it has been truncated +because of *max_lines*. Building on these capabilities, a new convenience +function :func:`~textwrap.shorten` collapses all of the whitespace in the input +to single spaces and produces a single line of a given *width* that ends with +the *placeholder* (by default, ``[...]``). (Contributed by Antoine Pitrou and +Serhiy Storchaka in :issue:`18585` and :issue:`18725`.) threading -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 00:35:07 2014 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 28 Feb 2014 00:35:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNzkx?= =?utf-8?q?=3A_copy=2Ecopy=28=29_now_doesn=27t_make_a_copy_when_the_input_?= =?utf-8?q?is_a_bytes?= Message-ID: <3fZqx73Z4nz7Lr2@mail.python.org> http://hg.python.org/cpython/rev/b3fb7828b6fc changeset: 89416:b3fb7828b6fc branch: 3.3 parent: 89407:8afcfe6dfd6e user: Antoine Pitrou date: Thu Feb 27 22:14:31 2014 +0100 summary: Issue #20791: copy.copy() now doesn't make a copy when the input is a bytes object. Initial patch by Peter Otten. files: Lib/copy.py | 2 +- Lib/test/test_copy.py | 1 + Misc/NEWS | 3 +++ 3 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/copy.py b/Lib/copy.py --- a/Lib/copy.py +++ b/Lib/copy.py @@ -110,7 +110,7 @@ def _copy_immutable(x): return x for t in (type(None), int, float, bool, str, tuple, - frozenset, type, range, + bytes, frozenset, type, range, types.BuiltinFunctionType, type(Ellipsis), types.FunctionType, weakref.ref): d[t] = _copy_immutable diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py --- a/Lib/test/test_copy.py +++ b/Lib/test/test_copy.py @@ -98,6 +98,7 @@ pass tests = [None, 42, 2**100, 3.14, True, False, 1j, "hello", "hello\u1234", f.__code__, + b"world", bytes(range(256)), NewStyle, range(10), Classic, max, WithMetaclass] for x in tests: self.assertIs(copy.copy(x), x) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -26,6 +26,9 @@ Library ------- +- Issue #20791: copy.copy() now doesn't make a copy when the input is + a bytes object. Initial patch by Peter Otten. + - Issue #20621: Fixes a zipimport bug introduced in 3.3.4 that could cause spurious crashes or SystemErrors when importing modules or packages from a zip file. The change causing the problem was reverted. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 00:35:09 2014 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 28 Feb 2014 00:35:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <3fZqx91sH3z7Lr1@mail.python.org> http://hg.python.org/cpython/rev/2d314e91025f changeset: 89417:2d314e91025f parent: 89415:9e8605ef7099 parent: 89416:b3fb7828b6fc user: Antoine Pitrou date: Fri Feb 28 00:34:47 2014 +0100 summary: Null merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 00:48:52 2014 From: python-checkins at python.org (terry.reedy) Date: Fri, 28 Feb 2014 00:48:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIwNTY3?= =?utf-8?q?=3A_Delete_class_attribute_gui_widgets_in_idle_tests=2E?= Message-ID: <3fZrF0433vz7Ljg@mail.python.org> http://hg.python.org/cpython/rev/43c4073cb2e2 changeset: 89418:43c4073cb2e2 branch: 2.7 parent: 89403:1a1a9d6fb278 user: Terry Jan Reedy date: Thu Feb 27 18:47:23 2014 -0500 summary: Issue #20567: Delete class attribute gui widgets in idle tests. Code patch by Serhiy Storchaka files: Lib/idlelib/idle_test/README.txt | 8 +++++--- Lib/idlelib/idle_test/test_formatparagraph.py | 3 +++ Lib/idlelib/idle_test/test_idlehistory.py | 1 + Lib/idlelib/idle_test/test_searchengine.py | 3 +++ Lib/idlelib/idle_test/test_text.py | 1 + Lib/test/test_idle.py | 1 + 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -41,9 +41,10 @@ screen, gui tests must be 'guarded' by "requires('gui')" in a setUp function or method. This will typically be setUpClass. -All gui objects must be destroyed by the end of the test, perhaps in a tearDown -function. Creating the Tk root directly in a setUp allows a reference to be saved -so it can be properly destroyed in the corresponding tearDown. +To avoid interfering with other gui tests, all gui objects must be destroyed +and deleted by the end of the test. If a widget, such as a Tk root, is created +in a setUpX function, destroy it in the corresponding tearDownX. For module +and class attributes, also delete the widget. --- @classmethod def setUpClass(cls): @@ -53,6 +54,7 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root --- Support.requires('gui') returns true if it is either called in a main module diff --git a/Lib/idlelib/idle_test/test_formatparagraph.py b/Lib/idlelib/idle_test/test_formatparagraph.py --- a/Lib/idlelib/idle_test/test_formatparagraph.py +++ b/Lib/idlelib/idle_test/test_formatparagraph.py @@ -277,6 +277,9 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root + del cls.text + del cls.formatter def test_short_line(self): self.text.insert('1.0', "Short line\n") diff --git a/Lib/idlelib/idle_test/test_idlehistory.py b/Lib/idlelib/idle_test/test_idlehistory.py --- a/Lib/idlelib/idle_test/test_idlehistory.py +++ b/Lib/idlelib/idle_test/test_idlehistory.py @@ -80,6 +80,7 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root def fetch_test(self, reverse, line, prefix, index, bell=False): # Perform one fetch as invoked by Alt-N or Alt-P diff --git a/Lib/idlelib/idle_test/test_searchengine.py b/Lib/idlelib/idle_test/test_searchengine.py --- a/Lib/idlelib/idle_test/test_searchengine.py +++ b/Lib/idlelib/idle_test/test_searchengine.py @@ -64,6 +64,7 @@ ## @classmethod ## def tearDownClass(cls): ## cls.root.destroy() +## del cls.root def test_get_selection(self): # text = Text(master=self.root) @@ -219,6 +220,7 @@ ## @classmethod ## def tearDownClass(cls): ## cls.root.destroy() +## del cls.root def test_search(self): Equal = self.assertEqual @@ -261,6 +263,7 @@ ## @classmethod ## def tearDownClass(cls): ## cls.root.destroy() +## del cls.root @classmethod def setUpClass(cls): diff --git a/Lib/idlelib/idle_test/test_text.py b/Lib/idlelib/idle_test/test_text.py --- a/Lib/idlelib/idle_test/test_text.py +++ b/Lib/idlelib/idle_test/test_text.py @@ -221,6 +221,7 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root if __name__ == '__main__': diff --git a/Lib/test/test_idle.py b/Lib/test/test_idle.py --- a/Lib/test/test_idle.py +++ b/Lib/test/test_idle.py @@ -14,6 +14,7 @@ try: root = tk.Tk() root.destroy() + del root except tk.TclError: while 'gui' in use_resources: use_resources.remove('gui') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 00:48:54 2014 From: python-checkins at python.org (terry.reedy) Date: Fri, 28 Feb 2014 00:48:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNTY3?= =?utf-8?q?=3A_Delete_class_attribute_gui_widgets_in_idle_tests=2E?= Message-ID: <3fZrF20783z7Lpw@mail.python.org> http://hg.python.org/cpython/rev/daf44eb9c54e changeset: 89419:daf44eb9c54e branch: 3.3 parent: 89416:b3fb7828b6fc user: Terry Jan Reedy date: Thu Feb 27 18:47:49 2014 -0500 summary: Issue #20567: Delete class attribute gui widgets in idle tests. Code patch by Serhiy Storchaka files: Lib/idlelib/idle_test/README.txt | 8 +++++--- Lib/idlelib/idle_test/test_formatparagraph.py | 3 +++ Lib/idlelib/idle_test/test_idlehistory.py | 1 + Lib/idlelib/idle_test/test_searchengine.py | 3 +++ Lib/idlelib/idle_test/test_text.py | 1 + Lib/test/test_idle.py | 1 + 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -41,9 +41,10 @@ screen, gui tests must be 'guarded' by "requires('gui')" in a setUp function or method. This will typically be setUpClass. -All gui objects must be destroyed by the end of the test, perhaps in a tearDown -function. Creating the Tk root directly in a setUp allows a reference to be saved -so it can be properly destroyed in the corresponding tearDown. +To avoid interfering with other gui tests, all gui objects must be destroyed +and deleted by the end of the test. If a widget, such as a Tk root, is created +in a setUpX function, destroy it in the corresponding tearDownX. For module +and class attributes, also delete the widget. --- @classmethod def setUpClass(cls): @@ -53,6 +54,7 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root --- Support.requires('gui') returns true if it is either called in a main module diff --git a/Lib/idlelib/idle_test/test_formatparagraph.py b/Lib/idlelib/idle_test/test_formatparagraph.py --- a/Lib/idlelib/idle_test/test_formatparagraph.py +++ b/Lib/idlelib/idle_test/test_formatparagraph.py @@ -277,6 +277,9 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root + del cls.text + del cls.formatter def test_short_line(self): self.text.insert('1.0', "Short line\n") diff --git a/Lib/idlelib/idle_test/test_idlehistory.py b/Lib/idlelib/idle_test/test_idlehistory.py --- a/Lib/idlelib/idle_test/test_idlehistory.py +++ b/Lib/idlelib/idle_test/test_idlehistory.py @@ -80,6 +80,7 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root def fetch_test(self, reverse, line, prefix, index, *, bell=False): # Perform one fetch as invoked by Alt-N or Alt-P diff --git a/Lib/idlelib/idle_test/test_searchengine.py b/Lib/idlelib/idle_test/test_searchengine.py --- a/Lib/idlelib/idle_test/test_searchengine.py +++ b/Lib/idlelib/idle_test/test_searchengine.py @@ -64,6 +64,7 @@ ## @classmethod ## def tearDownClass(cls): ## cls.root.destroy() +## del cls.root def test_get_selection(self): # text = Text(master=self.root) @@ -219,6 +220,7 @@ ## @classmethod ## def tearDownClass(cls): ## cls.root.destroy() +## del cls.root def test_search(self): Equal = self.assertEqual @@ -261,6 +263,7 @@ ## @classmethod ## def tearDownClass(cls): ## cls.root.destroy() +## del cls.root @classmethod def setUpClass(cls): diff --git a/Lib/idlelib/idle_test/test_text.py b/Lib/idlelib/idle_test/test_text.py --- a/Lib/idlelib/idle_test/test_text.py +++ b/Lib/idlelib/idle_test/test_text.py @@ -221,6 +221,7 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root if __name__ == '__main__': diff --git a/Lib/test/test_idle.py b/Lib/test/test_idle.py --- a/Lib/test/test_idle.py +++ b/Lib/test/test_idle.py @@ -14,6 +14,7 @@ try: root = tk.Tk() root.destroy() + del root except tk.TclError: while 'gui' in use_resources: use_resources.remove('gui') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 00:48:57 2014 From: python-checkins at python.org (terry.reedy) Date: Fri, 28 Feb 2014 00:48:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3fZrF5618mz7LjW@mail.python.org> http://hg.python.org/cpython/rev/c8c9971bdc53 changeset: 89420:c8c9971bdc53 parent: 89417:2d314e91025f parent: 89419:daf44eb9c54e user: Terry Jan Reedy date: Thu Feb 27 18:48:13 2014 -0500 summary: Merge with 3.3 files: Lib/idlelib/idle_test/README.txt | 8 +++++--- Lib/idlelib/idle_test/test_formatparagraph.py | 3 +++ Lib/idlelib/idle_test/test_idlehistory.py | 1 + Lib/idlelib/idle_test/test_searchengine.py | 3 +++ Lib/idlelib/idle_test/test_text.py | 1 + Lib/test/test_idle.py | 1 + 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -41,9 +41,10 @@ screen, gui tests must be 'guarded' by "requires('gui')" in a setUp function or method. This will typically be setUpClass. -All gui objects must be destroyed by the end of the test, perhaps in a tearDown -function. Creating the Tk root directly in a setUp allows a reference to be saved -so it can be properly destroyed in the corresponding tearDown. +To avoid interfering with other gui tests, all gui objects must be destroyed +and deleted by the end of the test. If a widget, such as a Tk root, is created +in a setUpX function, destroy it in the corresponding tearDownX. For module +and class attributes, also delete the widget. --- @classmethod def setUpClass(cls): @@ -53,6 +54,7 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root --- Support.requires('gui') returns true if it is either called in a main module diff --git a/Lib/idlelib/idle_test/test_formatparagraph.py b/Lib/idlelib/idle_test/test_formatparagraph.py --- a/Lib/idlelib/idle_test/test_formatparagraph.py +++ b/Lib/idlelib/idle_test/test_formatparagraph.py @@ -277,6 +277,9 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root + del cls.text + del cls.formatter def test_short_line(self): self.text.insert('1.0', "Short line\n") diff --git a/Lib/idlelib/idle_test/test_idlehistory.py b/Lib/idlelib/idle_test/test_idlehistory.py --- a/Lib/idlelib/idle_test/test_idlehistory.py +++ b/Lib/idlelib/idle_test/test_idlehistory.py @@ -80,6 +80,7 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root def fetch_test(self, reverse, line, prefix, index, *, bell=False): # Perform one fetch as invoked by Alt-N or Alt-P diff --git a/Lib/idlelib/idle_test/test_searchengine.py b/Lib/idlelib/idle_test/test_searchengine.py --- a/Lib/idlelib/idle_test/test_searchengine.py +++ b/Lib/idlelib/idle_test/test_searchengine.py @@ -64,6 +64,7 @@ ## @classmethod ## def tearDownClass(cls): ## cls.root.destroy() +## del cls.root def test_get_selection(self): # text = Text(master=self.root) @@ -219,6 +220,7 @@ ## @classmethod ## def tearDownClass(cls): ## cls.root.destroy() +## del cls.root def test_search(self): Equal = self.assertEqual @@ -261,6 +263,7 @@ ## @classmethod ## def tearDownClass(cls): ## cls.root.destroy() +## del cls.root @classmethod def setUpClass(cls): diff --git a/Lib/idlelib/idle_test/test_text.py b/Lib/idlelib/idle_test/test_text.py --- a/Lib/idlelib/idle_test/test_text.py +++ b/Lib/idlelib/idle_test/test_text.py @@ -221,6 +221,7 @@ @classmethod def tearDownClass(cls): cls.root.destroy() + del cls.root if __name__ == '__main__': diff --git a/Lib/test/test_idle.py b/Lib/test/test_idle.py --- a/Lib/test/test_idle.py +++ b/Lib/test/test_idle.py @@ -14,6 +14,7 @@ try: root = tk.Tk() root.destroy() + del root except tk.TclError: while 'gui' in use_resources: use_resources.remove('gui') -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Feb 28 08:49:26 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 28 Feb 2014 08:49:26 +0100 Subject: [Python-checkins] Daily reference leaks (c8c9971bdc53): sum=4 Message-ID: results for c8c9971bdc53 on branch "default" -------------------------------------------- test_site leaked [0, 0, 2] references, sum=2 test_site leaked [0, 0, 2] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogY7ApE1', '-x'] From python-checkins at python.org Fri Feb 28 14:35:21 2014 From: python-checkins at python.org (nick.coghlan) Date: Fri, 28 Feb 2014 14:35:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320757=3A_return_s?= =?utf-8?q?uccess_for_skipped_pip_uninstall?= Message-ID: <3fbBZd3cbTz7Lk9@mail.python.org> http://hg.python.org/cpython/rev/82ec02db7fe6 changeset: 89421:82ec02db7fe6 user: Nick Coghlan date: Fri Feb 28 23:35:05 2014 +1000 summary: Close #20757: return success for skipped pip uninstall The 3.4rc2 Windows uninstaller would fail if pip had been updated to a version that didn't match the version installed by ensurepip. This skip is no longer treated as an error, so an updated pip ends up being handled like any other pip installed package and is left alone by the CPython uninstaller. files: Lib/ensurepip/__init__.py | 5 +++-- Lib/test/test_ensurepip.py | 6 ++++-- Misc/NEWS | 7 +++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -128,9 +128,10 @@ # If the pip version doesn't match the bundled one, leave it alone if pip.__version__ != _PIP_VERSION: - msg = ("ensurepip will only uninstall a matching pip " + msg = ("ensurepip will only uninstall a matching version " "({!r} installed, {!r} bundled)") - raise RuntimeError(msg.format(pip.__version__, _PIP_VERSION)) + print(msg.format(pip.__version__, _PIP_VERSION), file=sys.stderr) + return _require_ssl_for_pip() _disable_pip_configuration_settings() diff --git a/Lib/test/test_ensurepip.py b/Lib/test/test_ensurepip.py --- a/Lib/test/test_ensurepip.py +++ b/Lib/test/test_ensurepip.py @@ -196,10 +196,12 @@ ensurepip._uninstall_helper() self.run_pip.assert_not_called() - def test_uninstall_fails_with_wrong_version(self): + def test_uninstall_skipped_with_warning_for_wrong_version(self): with fake_pip("not a valid version"): - with self.assertRaises(RuntimeError): + with test.support.captured_stderr() as stderr: ensurepip._uninstall_helper() + warning = stderr.getvalue().strip() + self.assertIn("only uninstall a matching version", warning) self.run_pip.assert_not_called() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -31,6 +31,13 @@ - Issue #20743: Fix a reference leak in test_tcl. +Build +----- + +- Issue #20757: The ensurepip helper for the Windows uninstaller now skips + uninstalling pip (rather than failing) if the user has updated pip to a + different version from the one bundled with ensurepip. + Tools/Demos ----------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 14:37:47 2014 From: python-checkins at python.org (nick.coghlan) Date: Fri, 28 Feb 2014 14:37:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2320568=3A_install_?= =?utf-8?q?unversioned_pip_command_on_Windows?= Message-ID: <3fbBdR6K6kz7LjM@mail.python.org> http://hg.python.org/cpython/rev/ec42ab5e0cb3 changeset: 89422:ec42ab5e0cb3 user: Nick Coghlan date: Fri Feb 28 23:37:35 2014 +1000 summary: Close #20568: install unversioned pip command on Windows files: Misc/NEWS | 3 +++ Tools/msi/msi.py | 2 +- 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,9 @@ Build ----- +- Issue #20568: The Windows installer now installs the unversioned ``pip`` + command in addition to the versioned ``pip3`` and ``pip3.4`` commands. + - Issue #20757: The ensurepip helper for the Windows uninstaller now skips uninstalling pip (rather than failing) if the user has updated pip to a different version from the one bundled with ensurepip. diff --git a/Tools/msi/msi.py b/Tools/msi/msi.py --- a/Tools/msi/msi.py +++ b/Tools/msi/msi.py @@ -420,7 +420,7 @@ compileargs = r'-Wi "[TARGETDIR]Lib\compileall.py" -f -x "bad_coding|badsyntax|site-packages|py2_|lib2to3\\tests|venv\\scripts" "[TARGETDIR]Lib"' lib2to3args = r'-c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()"' - updatepipargs = r'-m ensurepip -U' + updatepipargs = r'-m ensurepip -U --default-install' removepipargs = r'-m ensurepip._uninstall' # See "CustomAction Table" add_data(db, "CustomAction", [ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 15:49:39 2014 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 28 Feb 2014 15:49:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNzMx?= =?utf-8?q?=3A_Properly_position_in_source_code_files_even_if_they?= Message-ID: <3fbDDM53gVz7Ljn@mail.python.org> http://hg.python.org/cpython/rev/ade5e4922a54 changeset: 89423:ade5e4922a54 branch: 3.3 parent: 89419:daf44eb9c54e user: Martin v. L?wis date: Fri Feb 28 15:27:29 2014 +0100 summary: Issue #20731: Properly position in source code files even if they are opened in text mode. Patch by Serhiy Storchaka. files: .hgeol | 2 ++ Lib/test/coding20731.py | 4 ++++ Lib/test/test_coding.py | 9 ++++++++- Misc/NEWS | 3 +++ Parser/tokenizer.c | 14 ++++++++++++-- 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.hgeol b/.hgeol --- a/.hgeol +++ b/.hgeol @@ -37,6 +37,8 @@ Lib/venv/scripts/nt/* = BIN +Lib/test/coding20731.py = BIN + # All other files (which presumably are human-editable) are "native". # This must be the last rule! diff --git a/Lib/test/coding20731.py b/Lib/test/coding20731.py new file mode 100644 --- /dev/null +++ b/Lib/test/coding20731.py @@ -0,0 +1,4 @@ +#coding:latin1 + + + diff --git a/Lib/test/test_coding.py b/Lib/test/test_coding.py --- a/Lib/test/test_coding.py +++ b/Lib/test/test_coding.py @@ -1,6 +1,6 @@ import unittest from test.support import TESTFN, unlink, unload -import importlib, os, sys +import importlib, os, sys, subprocess class CodingTest(unittest.TestCase): def test_bad_coding(self): @@ -58,6 +58,13 @@ self.assertTrue(c.exception.args[0].startswith(expected), msg=c.exception.args[0]) + def test_20731(self): + sub = subprocess.Popen([sys.executable, + os.path.join(os.path.dirname(__file__), + 'coding20731.py')], + stderr=subprocess.PIPE) + err = sub.communicate()[1] + self.assertEquals(err, b'') if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #20731: Properly position in source code files even if they + are opened in text mode. Patch by Serhiy Storchaka. + - Issue #19619: str.encode, bytes.decode and bytearray.decode now use an internal API to throw LookupError for known non-text encodings, rather than attempting the encoding or decoding operation and then throwing a diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -498,9 +498,13 @@ fd = fileno(tok->fp); /* Due to buffering the file offset for fd can be different from the file - * position of tok->fp. */ + * position of tok->fp. If tok->fp was opened in text mode on Windows, + * its file position counts CRLF as one char and can't be directly mapped + * to the file offset for fd. Instead we step back one byte and read to + * the end of line.*/ pos = ftell(tok->fp); - if (pos == -1 || lseek(fd, (off_t)pos, SEEK_SET) == (off_t)-1) { + if (pos == -1 || + lseek(fd, (off_t)(pos > 0 ? pos - 1 : pos), SEEK_SET) == (off_t)-1) { PyErr_SetFromErrnoWithFilename(PyExc_OSError, NULL); goto cleanup; } @@ -513,6 +517,12 @@ Py_XDECREF(tok->decoding_readline); readline = _PyObject_GetAttrId(stream, &PyId_readline); tok->decoding_readline = readline; + if (pos > 0) { + if (PyObject_CallObject(readline, NULL) == NULL) { + readline = NULL; + goto cleanup; + } + } cleanup: Py_XDECREF(stream); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 15:49:40 2014 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 28 Feb 2014 15:49:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E3?= Message-ID: <3fbDDN6Zghz7Ljc@mail.python.org> http://hg.python.org/cpython/rev/8ebd0f382f9d changeset: 89424:8ebd0f382f9d parent: 89420:c8c9971bdc53 parent: 89423:ade5e4922a54 user: Martin v. L?wis date: Fri Feb 28 15:43:36 2014 +0100 summary: Merge with 3.3 files: .hgeol | 2 ++ Lib/test/coding20731.py | 4 ++++ Lib/test/test_source_encoding.py | 9 +++++++++ Misc/NEWS | 3 +++ Parser/tokenizer.c | 14 ++++++++++++-- 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.hgeol b/.hgeol --- a/.hgeol +++ b/.hgeol @@ -38,6 +38,8 @@ Lib/venv/scripts/nt/* = BIN +Lib/test/coding20731.py = BIN + # All other files (which presumably are human-editable) are "native". # This must be the last rule! diff --git a/Lib/test/coding20731.py b/Lib/test/coding20731.py new file mode 100644 --- /dev/null +++ b/Lib/test/coding20731.py @@ -0,0 +1,4 @@ +#coding:latin1 + + + diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -5,6 +5,7 @@ import importlib import os import sys +import subprocess class SourceEncodingTest(unittest.TestCase): @@ -58,6 +59,14 @@ # two bytes in common with the UTF-8 BOM self.assertRaises(SyntaxError, eval, b'\xef\xbb\x20') + def test_20731(self): + sub = subprocess.Popen([sys.executable, + os.path.join(os.path.dirname(__file__), + 'coding20731.py')], + stderr=subprocess.PIPE) + err = sub.communicate()[1] + self.assertEquals(err, b'') + def test_error_message(self): compile(b'# -*- coding: iso-8859-15 -*-\n', 'dummy', 'exec') compile(b'\xef\xbb\xbf\n', 'dummy', 'exec') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -8,6 +8,9 @@ Core and Builtins ----------------- +- Issue #20731: Properly position in source code files even if they + are opened in text mode. Patch by Serhiy Storchaka. + - Issue #20637: Key-sharing now also works for instance dictionaries of subclasses. Patch by Peter Ingebretson. diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -498,9 +498,13 @@ fd = fileno(tok->fp); /* Due to buffering the file offset for fd can be different from the file - * position of tok->fp. */ + * position of tok->fp. If tok->fp was opened in text mode on Windows, + * its file position counts CRLF as one char and can't be directly mapped + * to the file offset for fd. Instead we step back one byte and read to + * the end of line.*/ pos = ftell(tok->fp); - if (pos == -1 || lseek(fd, (off_t)pos, SEEK_SET) == (off_t)-1) { + if (pos == -1 || + lseek(fd, (off_t)(pos > 0 ? pos - 1 : pos), SEEK_SET) == (off_t)-1) { PyErr_SetFromErrnoWithFilename(PyExc_OSError, NULL); goto cleanup; } @@ -513,6 +517,12 @@ Py_XDECREF(tok->decoding_readline); readline = _PyObject_GetAttrId(stream, &PyId_readline); tok->decoding_readline = readline; + if (pos > 0) { + if (PyObject_CallObject(readline, NULL) == NULL) { + readline = NULL; + goto cleanup; + } + } cleanup: Py_XDECREF(stream); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 15:49:42 2014 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 28 Feb 2014 15:49:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_heads?= Message-ID: <3fbDDQ0zlbz7LjY@mail.python.org> http://hg.python.org/cpython/rev/c781843c4cbb changeset: 89425:c781843c4cbb parent: 89422:ec42ab5e0cb3 parent: 89424:8ebd0f382f9d user: Martin v. L?wis date: Fri Feb 28 15:47:15 2014 +0100 summary: Merge heads files: .hgeol | 2 ++ Lib/test/coding20731.py | 4 ++++ Lib/test/test_source_encoding.py | 9 +++++++++ Misc/NEWS | 3 +++ Parser/tokenizer.c | 14 ++++++++++++-- 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.hgeol b/.hgeol --- a/.hgeol +++ b/.hgeol @@ -38,6 +38,8 @@ Lib/venv/scripts/nt/* = BIN +Lib/test/coding20731.py = BIN + # All other files (which presumably are human-editable) are "native". # This must be the last rule! diff --git a/Lib/test/coding20731.py b/Lib/test/coding20731.py new file mode 100644 --- /dev/null +++ b/Lib/test/coding20731.py @@ -0,0 +1,4 @@ +#coding:latin1 + + + diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -5,6 +5,7 @@ import importlib import os import sys +import subprocess class SourceEncodingTest(unittest.TestCase): @@ -58,6 +59,14 @@ # two bytes in common with the UTF-8 BOM self.assertRaises(SyntaxError, eval, b'\xef\xbb\x20') + def test_20731(self): + sub = subprocess.Popen([sys.executable, + os.path.join(os.path.dirname(__file__), + 'coding20731.py')], + stderr=subprocess.PIPE) + err = sub.communicate()[1] + self.assertEquals(err, b'') + def test_error_message(self): compile(b'# -*- coding: iso-8859-15 -*-\n', 'dummy', 'exec') compile(b'\xef\xbb\xbf\n', 'dummy', 'exec') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -8,6 +8,9 @@ Core and Builtins ----------------- +- Issue #20731: Properly position in source code files even if they + are opened in text mode. Patch by Serhiy Storchaka. + - Issue #20637: Key-sharing now also works for instance dictionaries of subclasses. Patch by Peter Ingebretson. diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -498,9 +498,13 @@ fd = fileno(tok->fp); /* Due to buffering the file offset for fd can be different from the file - * position of tok->fp. */ + * position of tok->fp. If tok->fp was opened in text mode on Windows, + * its file position counts CRLF as one char and can't be directly mapped + * to the file offset for fd. Instead we step back one byte and read to + * the end of line.*/ pos = ftell(tok->fp); - if (pos == -1 || lseek(fd, (off_t)pos, SEEK_SET) == (off_t)-1) { + if (pos == -1 || + lseek(fd, (off_t)(pos > 0 ? pos - 1 : pos), SEEK_SET) == (off_t)-1) { PyErr_SetFromErrnoWithFilename(PyExc_OSError, NULL); goto cleanup; } @@ -513,6 +517,12 @@ Py_XDECREF(tok->decoding_readline); readline = _PyObject_GetAttrId(stream, &PyId_readline); tok->decoding_readline = readline; + if (pos > 0) { + if (PyObject_CallObject(readline, NULL) == NULL) { + readline = NULL; + goto cleanup; + } + } cleanup: Py_XDECREF(stream); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 15:49:43 2014 From: python-checkins at python.org (martin.v.loewis) Date: Fri, 28 Feb 2014 15:49:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Reindent?= Message-ID: <3fbDDR2DhCz7Ljs@mail.python.org> http://hg.python.org/cpython/rev/9b7abecf08e5 changeset: 89426:9b7abecf08e5 user: Martin v. L?wis date: Fri Feb 28 15:49:06 2014 +0100 summary: Reindent files: Lib/test/test_source_encoding.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_source_encoding.py b/Lib/test/test_source_encoding.py --- a/Lib/test/test_source_encoding.py +++ b/Lib/test/test_source_encoding.py @@ -60,7 +60,7 @@ self.assertRaises(SyntaxError, eval, b'\xef\xbb\x20') def test_20731(self): - sub = subprocess.Popen([sys.executable, + sub = subprocess.Popen([sys.executable, os.path.join(os.path.dirname(__file__), 'coding20731.py')], stderr=subprocess.PIPE) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 16:06:30 2014 From: python-checkins at python.org (brett.cannon) Date: Fri, 28 Feb 2014 16:06:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320650=3A_Tweak_so?= =?utf-8?q?me_awkward_wording=2E?= Message-ID: <3fbDbp0RVMz7LkC@mail.python.org> http://hg.python.org/cpython/rev/2dd7b9618596 changeset: 89427:2dd7b9618596 user: Brett Cannon date: Fri Feb 28 10:06:18 2014 -0500 summary: Issue #20650: Tweak some awkward wording. files: Doc/library/asyncio-eventloop.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -589,8 +589,8 @@ Arrange for a callback to be called in the specified executor. - *executor* is a :class:`~concurrent.futures.Executor` instance, - the default executor is used if *executor* is ``None``. + The *executor* argument should be an :class:`~concurrent.futures.Executor` + instance. The default executor is used if *executor* is ``None``. This method is a :ref:`coroutine `. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 16:50:44 2014 From: python-checkins at python.org (brett.cannon) Date: Fri, 28 Feb 2014 16:50:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIwNzc4?= =?utf-8?q?=3A_Fix_modulefinder_to_work_with_bytecode-only_modules=2E?= Message-ID: <3fbFZr6J4Qz7Lqw@mail.python.org> http://hg.python.org/cpython/rev/432cb56db05d changeset: 89428:432cb56db05d branch: 3.3 parent: 89423:ade5e4922a54 user: Brett Cannon date: Fri Feb 28 10:44:45 2014 -0500 summary: Issue #20778: Fix modulefinder to work with bytecode-only modules. Bug filed and initial attempt at a patch by Bohuslav Kabrda. files: Lib/modulefinder.py | 2 +- Lib/test/test_modulefinder.py | 20 ++++++++++++++++++++ Misc/NEWS | 2 ++ 3 files changed, 23 insertions(+), 1 deletions(-) diff --git a/Lib/modulefinder.py b/Lib/modulefinder.py --- a/Lib/modulefinder.py +++ b/Lib/modulefinder.py @@ -287,7 +287,7 @@ if fp.read(4) != imp.get_magic(): self.msgout(2, "raise ImportError: Bad magic number", pathname) raise ImportError("Bad magic number in %s" % pathname) - fp.read(4) + fp.read(8) # Skip mtime and size. co = marshal.load(fp) else: co = None diff --git a/Lib/test/test_modulefinder.py b/Lib/test/test_modulefinder.py --- a/Lib/test/test_modulefinder.py +++ b/Lib/test/test_modulefinder.py @@ -1,5 +1,7 @@ import os import errno +import importlib.machinery +import py_compile import shutil import unittest import tempfile @@ -208,6 +210,14 @@ from . import * """] +bytecode_test = [ + "a", + ["a"], + [], + [], + "" +] + def open_file(path): dirname = os.path.dirname(path) @@ -288,6 +298,16 @@ def test_relative_imports_4(self): self._do_test(relative_import_test_4) + def test_bytecode(self): + base_path = os.path.join(TEST_DIR, 'a') + source_path = base_path + importlib.machinery.SOURCE_SUFFIXES[0] + bytecode_path = base_path + importlib.machinery.BYTECODE_SUFFIXES[0] + with open_file(source_path) as file: + file.write('testing_modulefinder = True\n') + py_compile.compile(source_path, cfile=bytecode_path) + os.remove(source_path) + self._do_test(bytecode_test) + def test_main(): support.run_unittest(ModuleFinderTest) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,8 @@ Library ------- +- Issue #20778: Fix modulefinder to work with bytecode-only modules. + - Issue #20791: copy.copy() now doesn't make a copy when the input is a bytes object. Initial patch by Peter Otten. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 16:50:46 2014 From: python-checkins at python.org (brett.cannon) Date: Fri, 28 Feb 2014 16:50:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge_for_issue_=2320778?= Message-ID: <3fbFZt16wBz7LpM@mail.python.org> http://hg.python.org/cpython/rev/b6e999c8907c changeset: 89429:b6e999c8907c parent: 89427:2dd7b9618596 parent: 89428:432cb56db05d user: Brett Cannon date: Fri Feb 28 10:50:34 2014 -0500 summary: merge for issue #20778 files: Lib/modulefinder.py | 12 +++++++----- Lib/test/test_modulefinder.py | 20 ++++++++++++++++++++ Misc/NEWS | 2 ++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Lib/modulefinder.py b/Lib/modulefinder.py --- a/Lib/modulefinder.py +++ b/Lib/modulefinder.py @@ -1,6 +1,7 @@ """Find modules used by a script, using introspection.""" import dis +import importlib._bootstrap import importlib.machinery import marshal import os @@ -287,11 +288,12 @@ if type == imp.PY_SOURCE: co = compile(fp.read()+'\n', pathname, 'exec') elif type == imp.PY_COMPILED: - if fp.read(4) != imp.get_magic(): - self.msgout(2, "raise ImportError: Bad magic number", pathname) - raise ImportError("Bad magic number in %s" % pathname) - fp.read(4) - co = marshal.load(fp) + try: + marshal_data = importlib._bootstrap._validate_bytecode_header(fp.read()) + except ImportError as exc: + self.msgout(2, "raise ImportError: " + str(exc), pathname) + raise + co = marshal.loads(marshal_data) else: co = None m = self.add_module(fqname) diff --git a/Lib/test/test_modulefinder.py b/Lib/test/test_modulefinder.py --- a/Lib/test/test_modulefinder.py +++ b/Lib/test/test_modulefinder.py @@ -1,5 +1,7 @@ import os import errno +import importlib.machinery +import py_compile import shutil import unittest import tempfile @@ -208,6 +210,14 @@ from . import * """] +bytecode_test = [ + "a", + ["a"], + [], + [], + "" +] + def open_file(path): dirname = os.path.dirname(path) @@ -288,6 +298,16 @@ def test_relative_imports_4(self): self._do_test(relative_import_test_4) + def test_bytecode(self): + base_path = os.path.join(TEST_DIR, 'a') + source_path = base_path + importlib.machinery.SOURCE_SUFFIXES[0] + bytecode_path = base_path + importlib.machinery.BYTECODE_SUFFIXES[0] + with open_file(source_path) as file: + file.write('testing_modulefinder = True\n') + py_compile.compile(source_path, cfile=bytecode_path) + os.remove(source_path) + self._do_test(bytecode_test) + def test_main(): support.run_unittest(ModuleFinderTest) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -17,6 +17,8 @@ Library ------- +- Issue #20778: Fix modulefinder to work with bytecode-only modules. + - Issue #20791: copy.copy() now doesn't make a copy when the input is a bytes object. Initial patch by Peter Otten. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Feb 28 18:53:36 2014 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 28 Feb 2014 18:53:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_257=3A_Drop_recommendatio?= =?utf-8?q?n_of_extra_blank_line_at_end_of_docstring=2E?= Message-ID: <3fbJJc4ypbz7LjM@mail.python.org> http://hg.python.org/peps/rev/a7b2b2d5b1d4 changeset: 5389:a7b2b2d5b1d4 user: Guido van Rossum date: Fri Feb 28 09:53:33 2014 -0800 summary: PEP 257: Drop recommendation of extra blank line at end of docstring. files: pep-0257.txt | 11 +++++------ 1 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pep-0257.txt b/pep-0257.txt --- a/pep-0257.txt +++ b/pep-0257.txt @@ -201,15 +201,14 @@ Keyword arguments: real -- the real part (default 0.0) imag -- the imaginary part (default 0.0) - """ - if imag == 0.0 and real == 0.0: return complex_zero + if imag == 0.0 and real == 0.0: + return complex_zero ... -The BDFL [3]_ recommends inserting a blank line between the last -paragraph in a multi-line docstring and its closing quotes, placing -the closing quotes on a line by themselves. This way, Emacs' -``fill-paragraph`` command can be used on it. +Unless the entire docstring fits on a line, place the closing quotes +on a line by themselves. This way, Emacs' ``fill-paragraph`` command +can be used on it. Handling Docstring Indentation -- Repository URL: http://hg.python.org/peps From zachary.ware at gmail.com Tue Feb 18 06:19:41 2014 From: zachary.ware at gmail.com (Zachary Ware) Date: Tue, 18 Feb 2014 05:19:41 -0000 Subject: [Python-checkins] cpython: Close #20656: Fix select.select() on OpenBSD 64-bit In-Reply-To: <3fSjmY758Hz7LjS@mail.python.org> References: <3fSjmY758Hz7LjS@mail.python.org> Message-ID: On Mon, Feb 17, 2014 at 6:36 PM, victor.stinner wrote: > http://hg.python.org/cpython/rev/79ccf36b0fd0 > changeset: 89239:79ccf36b0fd0 > user: Victor Stinner > date: Tue Feb 18 01:35:40 2014 +0100 > summary: > Close #20656: Fix select.select() on OpenBSD 64-bit > > files: > Modules/selectmodule.c | 22 ++++++++++++---------- > 1 files changed, 12 insertions(+), 10 deletions(-) This changeset caused a compile warning on 32-bit Windows: ..\Modules\selectmodule.c(238): warning C4244: '=' : conversion from 'time_t' to 'long', possible loss of data [P:\ath\to\cpython\PCbuild\select.vcxproj] > diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c > --- a/Modules/selectmodule.c > +++ b/Modules/selectmodule.c > @@ -212,11 +212,18 @@ > return NULL; > } > else { > -#ifdef MS_WINDOWS > + /* On OpenBSD 5.4, timeval.tv_sec is a long. > + * Example: long is 64-bit, whereas time_t is 32-bit. */ > time_t sec; > - if (_PyTime_ObjectToTimeval(tout, &sec, &tv.tv_usec, > + /* On OS X 64-bit, timeval.tv_usec is an int (and thus still 4 > + bytes as required), but no longer defined by a long. */ > + long usec; > + if (_PyTime_ObjectToTimeval(tout, &sec, &usec, > _PyTime_ROUND_UP) == -1) > return NULL; > +#ifdef MS_WINDOWS > + /* On Windows, timeval.tv_sec is a long (32 bit), > + * whereas time_t can be 64-bit. */ > assert(sizeof(tv.tv_sec) == sizeof(long)); > #if SIZEOF_TIME_T > SIZEOF_LONG > if (sec > LONG_MAX) { > @@ -225,16 +232,11 @@ > return NULL; > } > #endif > - tv.tv_sec = (long)sec; > #else > - /* 64-bit OS X has struct timeval.tv_usec as an int (and thus still 4 > - bytes as required), but no longer defined by a long. */ > - long tv_usec; > - if (_PyTime_ObjectToTimeval(tout, &tv.tv_sec, &tv_usec, > - _PyTime_ROUND_UP) == -1) > - return NULL; > - tv.tv_usec = tv_usec; > + assert(sizeof(tv.tv_sec) >= sizeof(sec)); > #endif > + tv.tv_sec = sec; This is the offending line. I'm not sure how best to fix it, so I'm just pointing it out :) -- Zach